Merge branch 'lineage-17.1' of https://github.com/LineageOS/android_packages_apps_Gallery2 into int/10/fp2

Gallery2 from AOSP is not very polished and buggy in some cases. The
branch from LineageOS contains many improvements and fixes from also
CodeAurora, so take those sources instead.

This essentially replaces the current code with the code from the
LineageOS branch.

Issue: FP2A10-185
Issue: FP2A10-187
Change-Id: I7316386d0049211faa15d138e69240a81fdf3338
diff --git a/Android.mk b/Android.mk
index 9d0a90a..6e6dff8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,17 +1,22 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
 
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
 
+LOCAL_JAVA_LIBRARIES := telephony-common
+
 LOCAL_STATIC_ANDROID_LIBRARIES := \
+    com.google.android.material_material \
+    androidx.annotation_annotation \
     androidx.fragment_fragment \
+    androidx.heifwriter_heifwriter \
     androidx.legacy_legacy-support-core-ui \
     androidx.core_core \
     androidx.legacy_legacy-support-v13
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    com.android.gallery3d.common2 \
+    org.codeaurora.gallery.common \
     xmp_toolkit \
     mp4parser
 
@@ -25,17 +30,28 @@
 LOCAL_USE_AAPT2 := true
 
 LOCAL_PACKAGE_NAME := Gallery2
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_PRODUCT_MODULE := true
 
 LOCAL_OVERRIDES_PACKAGES := Gallery Gallery3D GalleryNew3D
 
-LOCAL_SDK_VERSION := current
+LOCAL_AAPT_FLAGS += --rename-manifest-package com.android.gallery3d
 
 LOCAL_JNI_SHARED_LIBRARIES := \
-    libjni_eglfence \
-    libjni_filtershow_filters \
-    libjni_jpegstream
+    libjni_gallery_eglfence \
+    libjni_gallery_filters \
+    libjni_gallery_jpegstream
+
+LOCAL_SHARED_LIBRARIES += \
+    libjni_dualcamera \
+    libjni_trueportrait \
+    libjni_filtergenerator
+
+LOCAL_REQUIRED_MODULES := libts_detected_face_jni libts_face_beautify_jni
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
@@ -43,11 +59,18 @@
 
 LOCAL_JARJAR_RULES := $(LOCAL_PATH)/jarjar-rules.txt
 
+LOCAL_REQUIRED_MODULES += privapp_whitelist_com.android.gallery3d.xml
+
 include $(BUILD_PACKAGE)
 
-ifeq ($(strip $(LOCAL_PACKAGE_OVERRIDES)),)
+include $(CLEAR_VARS)
+LOCAL_MODULE := privapp_whitelist_com.android.gallery3d.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
+LOCAL_PRODUCT_MODULE := true
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
 
 # Use the following include to make gallery test apk
 include $(call all-makefiles-under, $(LOCAL_PATH))
-
-endif
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
old mode 100644
new mode 100755
index 43439f9..bb731e2
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,28 +1,48 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2010-2014, 2016-2017 The Linux Foundation. All rights reserved.
+     Not a Contribution.
+
+     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.
+-->
 
 <manifest android:versionCode="40030"
         android:versionName="1.1.40030"
         xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.gallery3d">
+        package="org.codeaurora.gallery">
 
     <original-package android:name="com.android.gallery3d" />
 
-    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="28" />
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28"/>
 
     <permission android:name="com.android.gallery3d.permission.GALLERY_PROVIDER"
-            android:protectionLevel="signatureOrSystem" />
+                android:protectionLevel="signatureOrSystem" />
 
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <permission android:name="org.codeaurora.gallery.filtershow.permission.READ"
+                android:protectionLevel="signature" />
+
+    <permission android:name="org.codeaurora.gallery.filtershow.permission.WRITE"
+                android:protectionLevel="signature" />
+
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.NFC" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-    <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />
     <uses-permission android:name="android.permission.VIBRATE" />
@@ -31,25 +51,30 @@
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
     <uses-permission android:name="com.android.gallery3d.permission.GALLERY_PROVIDER" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <!-- add for guest to set system property -->
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
 
     <supports-screens android:smallScreens="false"
             android:normalScreens="true" android:largeScreens="true"
             android:anyDensity="true" />
 
-    <application android:icon="@mipmap/ic_launcher_gallery" android:label="@string/app_name"
+    <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
             android:name="com.android.gallery3d.app.GalleryAppImpl"
-            android:theme="@style/Theme.Gallery"
-            android:logo="@mipmap/ic_launcher_gallery"
+            android:logo="@mipmap/ic_launcher"
             android:hardwareAccelerated="true"
             android:largeHeap="true"
+            android:appCategory="image"
             android:restoreAnyVersion="true"
             android:supportsRtl="true"
-            usesCleartextHttp="true">
+            android:usesCleartextTraffic="true">
         <uses-library android:name="com.google.android.media.effects" android:required="false" />
         <uses-library android:name="org.apache.http.legacy" android:required="false" />
         <activity android:name="com.android.gallery3d.app.MovieActivity"
                 android:label="@string/movie_view_label"
-                android:configChanges="orientation|keyboardHidden|screenSize">
+                android:theme="@style/Theme.MovieActivity"
+                android:configChanges="orientation|keyboardHidden|screenSize|keyboard">
             <intent-filter>
                 <action android:name="android.intent.action.VIEW" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -64,14 +89,8 @@
                 <data android:scheme="https" />
                 <data android:scheme="content" />
                 <data android:scheme="file" />
-                <data android:mimeType="video/mpeg4" />
-                <data android:mimeType="video/mp4" />
-                <data android:mimeType="video/3gp" />
-                <data android:mimeType="video/3gpp" />
-                <data android:mimeType="video/3gpp2" />
-                <data android:mimeType="video/webm" />
-                <data android:mimeType="video/avi" />
-                <data android:mimeType="application/sdp" />
+                <data android:scheme="rtsp" />
+                <data android:mimeType="video/*" />
              </intent-filter>
              <intent-filter>
                 <!-- HTTP live support -->
@@ -84,11 +103,13 @@
                 <data android:mimeType="audio/mpegurl" />
                 <data android:mimeType="application/vnd.apple.mpegurl" />
                 <data android:mimeType="application/x-mpegurl" />
+                <data android:mimeType="application/dash+xml" />
              </intent-filter>
         </activity>
 
-        <activity android:name="com.android.gallery3d.app.GalleryActivity" android:label="@string/app_name"
-                android:configChanges="keyboardHidden|orientation|screenSize">
+        <activity android:name="com.android.gallery3d.app.GalleryActivity"
+                android:theme="@style/AppTheme"
+                android:configChanges="keyboardHidden|orientation|screenSize|locale|fontScale|layoutDirection">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -225,7 +246,9 @@
                     android:resource="@xml/wallpaper_picker_preview" />
         </activity>
         <activity android:name="com.android.gallery3d.app.TrimVideo"
-                android:label="@string/trim_label">
+                android:label="@string/trim_label"
+                android:theme="@style/Theme.MovieActivity"
+                android:configChanges="keyboardHidden|orientation|screenSize">
             <intent-filter android:label="@string/crop_label">
                 <action android:name="com.android.camera.action.TRIM" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -239,18 +262,17 @@
             android:name="com.android.gallery3d.filtershow.provider.SharedImageProvider"
             android:authorities="com.android.gallery3d.filtershow.provider.SharedImageProvider"
             android:grantUriPermissions="true"
-            android:readPermission="com.android.gallery3d.filtershow.permission.READ"
-            android:writePermission="com.android.gallery3d.filtershow.permission.WRITE" />
+            android:readPermission="org.codeaurora.gallery.filtershow.permission.READ"
+            android:writePermission="org.codeaurora.gallery.filtershow.permission.WRITE" />
 
         <service
-                android:name=".filtershow.pipeline.ProcessingService"
+                android:name="com.android.gallery3d.filtershow.pipeline.ProcessingService"
                 android:exported="false" />
 
         <activity
             android:name="com.android.gallery3d.filtershow.FilterShowActivity"
-            android:label="@string/title_activity_filter_show"
             android:theme="@style/Theme.FilterShow"
-            android:configChanges="keyboardHidden|orientation|screenSize">
+            android:configChanges="keyboardHidden|orientation|screenSize|locale|layoutDirection">
             <intent-filter>
                 <action android:name="android.intent.action.EDIT" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -267,7 +289,7 @@
             android:name="com.android.gallery3d.filtershow.crop.CropActivity"
             android:label="@string/crop"
             android:theme="@style/Theme.Crop"
-            android:configChanges="keyboardHidden|orientation|screenSize">
+            android:configChanges="keyboardHidden|orientation|screenSize|fontScale">
            <intent-filter android:label="@string/crop_label">
                 <action android:name="com.android.camera.action.CROP" />
                 <data android:scheme="content" />
@@ -286,6 +308,16 @@
                 android:theme="@style/Theme.Gallery"
                 android:configChanges="orientation|keyboardHidden|screenSize" />
 
+        <activity android:name="com.android.gallery3d.util.ViewGifImage"
+                android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
+                android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation">
+            <intent-filter>
+                <action android:name="com.android.gallery3d.VIEW_GIF" />
+                <data android:mimeType="image/gif" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
         <provider android:name="com.android.gallery3d.provider.GalleryProvider"
                 android:syncable="false"
                 android:grantUriPermissions="true"
@@ -297,7 +329,18 @@
                 android:authorities="com.android.gallery3d.photoprovider"
                 android:syncable="false"
                 android:exported="false"/>
-        <activity android:name="com.android.gallery3d.gadget.WidgetClickHandler" />
+        <provider
+            android:name="androidx.core.content.FileProvider"
+            android:authorities="com.android.gallery3d.fileprovider"
+            android:exported="false"
+            android:grantUriPermissions="true">
+            <meta-data
+                android:name="android.support.FILE_PROVIDER_PATHS"
+                android:resource="@xml/provider_paths"/>
+        </provider>
+        <activity
+                android:name="com.android.gallery3d.gadget.WidgetClickHandler"
+                android:theme="@android:style/Theme.NoDisplay" />
         <activity android:name="com.android.gallery3d.app.DialogPicker"
                 android:configChanges="keyboardHidden|orientation|screenSize"
                 android:theme="@style/DialogPickerTheme"/>
@@ -316,17 +359,6 @@
             <meta-data android:name="android.appwidget.provider"
                     android:resource="@xml/widget_info" />
         </receiver>
-        <receiver android:name="com.android.gallery3d.app.PackagesMonitor">
-            <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_ADDED"/>
-                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
-                <action android:name="android.intent.action.PACKAGE_CHANGED"/>
-                <data android:scheme="package"/>
-            </intent-filter>
-        </receiver>
-        <service android:name="com.android.gallery3d.app.PackagesMonitor$AsyncService"
-                 android:permission="android.permission.BIND_JOB_SERVICE"
-                 android:exported="true"/>
         <service android:name="com.android.gallery3d.gadget.WidgetService"
                 android:permission="android.permission.BIND_REMOTEVIEWS"/>
         <activity android:name="com.android.gallery3d.gadget.WidgetConfigure"
@@ -345,5 +377,40 @@
         </receiver>
 
         <service android:name="com.android.camera.MediaSaveService" />
+
+        <activity android:name="org.codeaurora.gallery3d.video.SettingsActivity"
+                android:theme="@android:style/Theme.Material.Light"
+                android:configChanges="keyboardHidden|orientation|screenSize"
+                android:label="@string/streaming_settings" >
+            <intent-filter>
+                <action android:name="org.codeaurora.settings.streaming" />
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+        <receiver android:name="org.codeaurora.gallery3d.video.DmReceiver" >
+            <intent-filter>
+                <action android:name="streaming.action.WRITE_SETTINGS" />
+            </intent-filter>
+        </receiver>
+
+        <activity android:name="org.codeaurora.gallery3d.video.BookmarkActivity"
+                android:configChanges="keyboardHidden|orientation|screenSize"
+                android:icon="@drawable/ic_menu_display_bookmark"
+                android:label="@string/bookmark_list"
+                android:theme="@android:style/Theme.Holo" >
+            <intent-filter>
+                <action android:name="org.codeaurora.bookmark.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+        <activity android:name="org.codeaurora.gallery3d.video.VideoSettingsActivity"
+                android:label="@string/movie_view_label"
+                android:theme="@android:style/Theme.Material.Light"
+                android:configChanges="orientation|keyboardHidden|screenSize|mnc|mcc">
+        </activity>
+        <activity android:name="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity"
+            android:configChanges="orientation|screenSize|layoutDirection">
+        </activity>
     </application>
 </manifest>
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0576234..acd9fcc 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -51,9 +51,9 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Gallery*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Gallery*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Gallery2)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_jpegstream.so)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_eglfence.so)
-$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_filtershow_filters.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_gallery_jpegstream.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_gallery_eglfence.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libjni_gallery_filters.so)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/OWNERS b/OWNERS
deleted file mode 100644
index ed1d60a..0000000
--- a/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default code reviewers picked from top 3 or more developers.
-# Please update this list if you find better candidates.
-rtenneti@google.com
diff --git a/gallerycommon/Android.mk b/gallerycommon/Android.mk
index 1d34147..735227f 100644
--- a/gallerycommon/Android.mk
+++ b/gallerycommon/Android.mk
@@ -20,8 +20,11 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE := com.android.gallery3d.common2
+LOCAL_MODULE := org.codeaurora.gallery.common
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SDK_VERSION := 16
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
old mode 100644
new mode 100755
index f4de5c9..4b8d961
--- a/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
+++ b/gallerycommon/src/com/android/gallery3d/common/ApiHelper.java
@@ -25,6 +25,8 @@
 import android.view.WindowManager;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
 public class ApiHelper {
     public static interface VERSION_CODES {
@@ -192,6 +194,9 @@
     public static final boolean HAS_DISPLAY_LISTENER =
             Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1;
 
+    // from android.provider.Settings.Global
+    public static final String MULTI_SIM_DATA_CALL_SUBSCRIPTION = "multi_sim_data_call";
+
     public static int getIntFieldIfExists(Class<?> klass, String fieldName,
             Class<?> obj, int defaultVal) {
         try {
@@ -202,6 +207,17 @@
         }
     }
 
+    public static boolean getBooleanFieldIfExists(Object obj, String fieldName,
+            boolean defaultVal) {
+        Class<?> klass = obj.getClass();
+        try {
+            Field f = klass.getDeclaredField(fieldName);
+            return f.getBoolean(obj);
+        } catch (Exception e) {
+            return defaultVal;
+        }
+    }
+
     private static boolean hasField(Class<?> klass, String fieldName) {
         try {
             klass.getDeclaredField(fieldName);
@@ -231,4 +247,149 @@
             return false;
         }
     }
+
+    private static Class<?> getClassForName(String className) {
+        Class<?> klass = null;
+        try {
+            klass = Class.forName(className);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        return klass;
+    }
+
+    private static Method getMethod(Class<?> klass, String name, Class<?>... parameterTypes) {
+        Method method = null;
+        if (klass != null) {
+            try {
+                method = klass.getMethod(name, parameterTypes);
+            } catch (NoSuchMethodException e) {
+                e.printStackTrace();
+            }
+        }
+        return method;
+    }
+
+    private static Object invoke(Method method, Object receiver, Object... args) {
+        Object obj = null;
+        if (method != null) {
+            try {
+                obj = method.invoke(receiver, args);
+            } catch (IllegalAccessException | InvocationTargetException e) {
+                e.printStackTrace();
+            }
+        }
+        return obj;
+    }
+
+    public static class SystemProperties {
+        private static final Method getIntMethod;
+        private static final Method getBooleanMethod;
+        private static final Method getMethod;
+        private static final Method setMethod;
+
+        static {
+            Class<?> klass = getClassForName("android.os.SystemProperties");
+            getIntMethod = getMethod(klass, "getInt", String.class, int.class);
+            getBooleanMethod = getMethod(klass, "getBoolean", String.class, boolean.class);
+            getMethod = getMethod(klass, "get", String.class, String.class);
+            setMethod = getMethod(klass, "set", String.class, String.class);
+        }
+
+        public static int getInt(String key, int def) {
+            Object obj = invoke(getIntMethod, null, key, def);
+            return obj == null ? def : (Integer) obj;
+        }
+
+        public static boolean getBoolean(String key, boolean def) {
+            Object obj = invoke(getBooleanMethod, null, key, def);
+            return obj == null ? def : (Boolean) obj;
+        }
+
+        public static String get(String key, String def) {
+            Object obj = invoke(getMethod, null, key, def);
+            return obj == null ? def : (String) obj;
+        }
+
+        public static void set(String key, String val) {
+            invoke(setMethod, null, key, val);
+        }
+    }
+
+    public static class Metadata {
+        public static final int PAUSE_AVAILABLE = 1;
+        public static final int SEEK_BACKWARD_AVAILABLE = 2;
+        public static final int SEEK_FORWARD_AVAILABLE = 3;
+        public static final int SEEK_AVAILABLE = 4;
+
+        private static final Method hasMethod;
+        private static final Method getIntMethod;
+        private static final Method getBooleanMethod;
+
+        static {
+            Class<?> klass = getClassForName("android.media.Metadata");
+            hasMethod = getMethod(klass, "has", int.class);
+            getIntMethod = getMethod(klass, "getInt", int.class);
+            getBooleanMethod = getMethod(klass, "getBoolean", int.class);
+        }
+
+        private Object mMetadata;
+
+        Metadata(Object obj) {
+            mMetadata = obj;
+        }
+
+        public boolean has(final int metadataId) {
+            Object obj = invoke(hasMethod, mMetadata, metadataId);
+            return obj == null ? false : (Boolean) obj;
+        }
+
+        public int getInt(final int key) {
+            Object obj = invoke(getIntMethod, mMetadata, key);
+            return obj == null ? 0 : (Integer) obj;
+        }
+
+        public boolean getBoolean(final int key) {
+            Object obj = invoke(getBooleanMethod, mMetadata, key);
+            return obj == null ? false : (Boolean) obj;
+        }
+    }
+
+    public static class MediaPlayer {
+        public static final boolean METADATA_ALL = false;
+        public static final boolean BYPASS_METADATA_FILTER = false;
+
+        public static Metadata getMetadata(android.media.MediaPlayer mp,
+                final boolean update_only, final boolean apply_filter) {
+            Method method = getMethod(mp.getClass(), "getMetadata", boolean.class, boolean.class);
+            Object obj = invoke(method, mp, update_only, apply_filter);
+            return obj == null ? null : new Metadata(obj);
+        }
+    }
+
+    public static class AudioSystem {
+        public static final int FORCE_NONE = 0;
+        public static final int FORCE_SPEAKER = 1;
+        public static final int FORCE_NO_BT_A2DP = 10;
+
+        public static final int FOR_MEDIA = 1;
+
+        private static final Method setForceUseMethod;
+        private static final Method getForceUseMethod;
+
+        static {
+            Class<?> klass = getClassForName("android.media.AudioSystem");
+            setForceUseMethod = getMethod(klass, "setForceUse", int.class, int.class);
+            getForceUseMethod = getMethod(klass, "getForceUse", int.class);
+        }
+
+        public static void setForceUse(int usage, int config) {
+            invoke(setForceUseMethod, null, usage, config);
+        }
+
+        public static int getForceUse(int usage) {
+            Object obj = invoke(getForceUseMethod, null, usage);
+            return obj == null ? FORCE_NONE : (Integer) obj;
+        }
+    }
 }
diff --git a/gallerycommon/src/com/android/gallery3d/common/OverScroller.java b/gallerycommon/src/com/android/gallery3d/common/OverScroller.java
index a03c451..6becb3a 100644
--- a/gallerycommon/src/com/android/gallery3d/common/OverScroller.java
+++ b/gallerycommon/src/com/android/gallery3d/common/OverScroller.java
@@ -855,7 +855,7 @@
             float distance = mVelocity * mVelocity / (2.0f * Math.abs(mDeceleration));
             final float sign = Math.signum(mVelocity);
 
-            if (distance > mOver) {
+            if (Math.abs(distance) > mOver) {
                 // Default deceleration is not sufficient to slow us down before boundary
                  mDeceleration = - sign * mVelocity * mVelocity / (2.0f * mOver);
                  distance = mOver;
diff --git a/gallerycommon/src/com/android/gallery3d/exif/CountedDataInputStream.java b/gallerycommon/src/com/android/gallery3d/exif/CountedDataInputStream.java
index dfd4a1a..c8300ad 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/CountedDataInputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/CountedDataInputStream.java
@@ -24,7 +24,7 @@
 import java.nio.ByteOrder;
 import java.nio.charset.Charset;
 
-class CountedDataInputStream extends FilterInputStream {
+public class CountedDataInputStream extends FilterInputStream {
 
     private int mCount = 0;
 
@@ -32,7 +32,7 @@
     private final byte mByteArray[] = new byte[8];
     private final ByteBuffer mByteBuffer = ByteBuffer.wrap(mByteArray);
 
-    protected CountedDataInputStream(InputStream in) {
+    public CountedDataInputStream(InputStream in) {
         super(in);
     }
 
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
index a1cf0fc..2142209 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
@@ -318,6 +318,13 @@
     public static final int TAG_INTEROPERABILITY_INDEX =
         defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, (short) 1);
 
+    private static final String GPS_DATE_FORMAT_STR = "yyyy:MM:dd";
+    private static final String DATETIME_FORMAT_STR = "yyyy:MM:dd kk:mm:ss";
+    public static final DateFormat DATETIME_FORMAT = new SimpleDateFormat(DATETIME_FORMAT_STR);
+    private final DateFormat mGPSDateStampFormat = new SimpleDateFormat(GPS_DATE_FORMAT_STR);
+    private final Calendar mGPSTimeStampCalendar = Calendar
+            .getInstance(TimeZone.getTimeZone("UTC"));
+
     /**
      * Tags that contain offset markers. These are included in the banned
      * defines.
@@ -732,7 +739,7 @@
      * @param inStream an InputStream containing a jpeg compressed image.
      * @throws IOException
      */
-    public void readExif(InputStream inStream) throws IOException {
+    public void readExif(InputStream inStream) throws IOException, NullPointerException {
         if (inStream == null) {
             throw new IllegalArgumentException(NULL_ARGUMENT_STRING);
         }
@@ -1944,13 +1951,6 @@
         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},
@@ -1964,8 +1964,8 @@
     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));
+            DATETIME_FORMAT.setTimeZone(timezone);
+            ExifTag t = buildTag(tagId, DATETIME_FORMAT.format(timestamp));
             if (t == null) {
                 return false;
             }
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
index 7ca05f2..123cb8d 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
@@ -25,6 +25,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This class provides a way to replace the Exif header of a JPEG image.
@@ -235,6 +236,7 @@
         dataOutputStream.writeInt(8);
         writeAllTags(dataOutputStream);
         writeThumbnail(dataOutputStream);
+        if (nullTags == null) return;
         for (ExifTag t : nullTags) {
             mExifData.addTag(t);
         }
@@ -242,7 +244,9 @@
 
     private ArrayList<ExifTag> stripNullValueTags(ExifData data) {
         ArrayList<ExifTag> nullTags = new ArrayList<ExifTag>();
-        for(ExifTag t : data.getAllTags()) {
+        List<ExifTag> listTags = data.getAllTags();
+        if (listTags == null) return null;
+        for(ExifTag t : listTags) {
             if (t.getValue() == null && !ExifInterface.isOffsetTag(t.getTagId())) {
                 data.removeTag(t.getTagId(), t.getIfd());
                 nullTags.add(t);
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
old mode 100644
new mode 100755
index 5467d42..ec653e9
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
@@ -143,6 +143,9 @@
 
     protected static final int DEFAULT_IFD0_OFFSET = 8;
 
+    //HEIC header
+    protected static final int HEIC_HEADER = 0x68656963;
+
     private final CountedDataInputStream mTiffStream;
     private final int mOptions;
     private int mIfdStartOffset = 0;
@@ -556,7 +559,8 @@
             }
             // Some invalid images put some undefined data before IFD0.
             // Read the data here.
-            if ((offset < mIfd0Position) && (dataFormat == ExifTag.TYPE_UNDEFINED)) {
+            if ((offset < mIfd0Position) && (dataFormat == ExifTag.TYPE_UNDEFINED)
+                    && (mIfd0Position > DEFAULT_IFD0_OFFSET)) {
                 byte[] buf = new byte[(int) numOfComp];
                 System.arraycopy(mDataAboveIfd0, (int) offset - DEFAULT_IFD0_OFFSET,
                         buf, 0, (int) numOfComp);
@@ -752,37 +756,66 @@
     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 (dataStream.readShort() == JpegHeader.SOI) {
+            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();
             }
-            if (length < 2 || (length - 2) != dataStream.skip(length - 2)) {
-                Log.w(TAG, "Invalid JPEG format.");
+
+
+        } else{
+            dataStream.skip(6);
+            if (dataStream.readInt() == HEIC_HEADER) {
+                while(true){
+                    try{
+                        short marker = dataStream.readShort();
+                        if (marker == JpegHeader.APP1) {
+                            int header = 0;
+                            short headerTail = 0;
+                            int length = dataStream.readUnsignedShort();
+                            header = dataStream.readInt();
+                            headerTail = dataStream.readShort();
+                            if (header == EXIF_HEADER && headerTail == EXIF_HEADER_TAIL) {
+                                mTiffStartPosition = dataStream.getReadByteCount();
+                                mApp1End = length;
+                                mOffsetToApp1EndFromSOF = mTiffStartPosition + mApp1End;
+                                return true;
+                            }
+                        }
+                    }catch (Exception e){
+                        break;
+                    }
+                }
                 return false;
+            } else {
+                throw new ExifInvalidFormatException("Invalid JPEG format");
             }
-            marker = dataStream.readShort();
+
         }
+
         return false;
     }
 
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java b/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
index b8b3872..c257bcd 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifTag.java
@@ -17,7 +17,6 @@
 package com.android.gallery3d.exif;
 
 import java.nio.charset.Charset;
-import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
 
@@ -102,8 +101,6 @@
     // 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.
      */
@@ -314,13 +311,17 @@
      * 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:
+     * the string must be equal to either
+     * <ul>
+     * <li>component count - 1 when the terminating '\0' is not present</li>
+     * <li>component count when the terminating '\0' is present</li>
+     * <li>to comply with some non-conformant implementations, the terminating
+     * '\0' will be appended if it's not present and component count equals
+     * the string length; the component count will be updated in that case</li>
+     * 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
+     * <li>The length of the string is not equal to (component count - 1) or
      * (component count) in the definition for this tag.</li>
      * </ul>
      */
@@ -331,11 +332,19 @@
 
         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 };
+        if (mDataType == TYPE_ASCII) {
+            if (buf.length > 0) {
+                if (buf[buf.length - 1] != 0) {
+                    finalBuf = Arrays.copyOf(buf, buf.length + 1);
+                    // Apply the workaround for non-conformant implementations
+                    // (e.g. Samsung Wave 2): accept a string with missing termination character
+                    if (mComponentCountActual == buf.length) {
+                        mComponentCountActual++;
+                    }
+                }
+            } else if (mComponentCountActual == 1) {
+                finalBuf = new byte[] { 0 };
+            }
         }
         int count = finalBuf.length;
         if (checkBadComponentCount(count)) {
@@ -524,9 +533,9 @@
      * @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)));
+        // synchronized on DATETIME_FORMAT as SimpleDateFormat is not thread safe
+        synchronized (ExifInterface.DATETIME_FORMAT) {
+            return setValue(ExifInterface.DATETIME_FORMAT.format(new Date(time)));
         }
     }
 
diff --git a/gallerycommon/src/com/android/gallery3d/exif/JpegHeader.java b/gallerycommon/src/com/android/gallery3d/exif/JpegHeader.java
index e3e787e..391d152 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/JpegHeader.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/JpegHeader.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.exif;
 
-class JpegHeader {
+public class JpegHeader {
     public static final short SOI =  (short) 0xFFD8;
     public static final short APP1 = (short) 0xFFE1;
     public static final short APP0 = (short) 0xFFE0;
diff --git a/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGInputStream.java b/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGInputStream.java
index 44ccd4c..71c3eb4 100644
--- a/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGInputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGInputStream.java
@@ -188,6 +188,6 @@
     native private int skipDecodedBytes(int bytes);
 
     static {
-        System.loadLibrary("jni_jpegstream");
+        System.loadLibrary("jni_gallery_jpegstream");
     }
 }
diff --git a/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGOutputStream.java b/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGOutputStream.java
index c49d375..ab5c3a9 100644
--- a/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGOutputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/jpegstream/JPEGOutputStream.java
@@ -139,6 +139,6 @@
     native private int writeInputBytes(byte[] inBuffer, int offset, int inCount);
 
     static {
-        System.loadLibrary("jni_jpegstream");
+        System.loadLibrary("jni_gallery_jpegstream");
     }
 }
diff --git a/jni/Android.mk b/jni/Android.mk
index c08d7be..6517d9b 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -1,16 +1,9 @@
 LOCAL_PATH:= $(call my-dir)
 
-Gallery2_jni_cflags := \
-    -Wall -Wextra -Werror \
-    -Wno-error=constant-conversion \
-    -Wno-unused-parameter \
-
-# to fix implicit conversion from 'int' to 'char', (255 to -1, 128 to -128)
-
 include $(CLEAR_VARS)
 
 LOCAL_CFLAGS += -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += $(Gallery2_jni_cflags)
+LOCAL_CFLAGS += -Wall -Wextra -Werror
 
 LOCAL_SRC_FILES := jni_egl_fence.cpp
 
@@ -18,7 +11,7 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_MODULE := libjni_eglfence
+LOCAL_MODULE := libjni_gallery_eglfence
 
 LOCAL_PRODUCT_MODULE := true
 
@@ -33,7 +26,7 @@
 
 LOCAL_CPP_EXTENSION := .cc
 LOCAL_SDK_VERSION := 9
-LOCAL_MODULE    := libjni_filtershow_filters
+LOCAL_MODULE    := libjni_gallery_filters
 LOCAL_PRODUCT_MODULE := true
 LOCAL_SRC_FILES := filters/gradient.c \
                    filters/saturated.c \
@@ -55,8 +48,8 @@
                    filters/tinyplanet.cc \
                    filters/kmeans.cc
 
-LOCAL_CFLAGS += -ffast-math -O3 -funroll-loops
-LOCAL_CFLAGS += $(Gallery2_jni_cflags)
+LOCAL_CFLAGS    += -ffast-math -O3 -funroll-loops
+LOCAL_CFLAGS += -Wall -Wextra -Werror
 LOCAL_LDLIBS := -llog -ljnigraphics
 LOCAL_ARM_MODE := arm
 
diff --git a/jni/filters/edge.c b/jni/filters/edge.c
index 9f5d88f..5e7be3c 100644
--- a/jni/filters/edge.c
+++ b/jni/filters/edge.c
@@ -19,7 +19,7 @@
 
 void JNIFUNCF(ImageFilterEdge, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat p)
 {
-    char* destination = 0;
+    uint8_t* destination = 0;
     AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
 
     // using contrast function:
@@ -32,15 +32,15 @@
     float const c_max = 500.0f;
 
     // pixels must be 4 bytes
-    char * dst = destination;
+    uint8_t* dst = destination;
 
     int j, k;
-    char * ptr = destination;
+    uint8_t* ptr = destination;
     int row_stride = 4 * width;
 
     // set 2 row buffer (avoids bitmap copy)
     int buf_len = 2 * row_stride;
-    char buf[buf_len];
+    uint8_t buf[buf_len];
     int buf_row_ring = 0;
 
     // set initial buffer to black
diff --git a/jni/filters/geometry.c b/jni/filters/geometry.c
index 8537549..c2d80f3 100644
--- a/jni/filters/geometry.c
+++ b/jni/filters/geometry.c
@@ -19,7 +19,7 @@
 
 #include "filters.h"
 
-static __inline__ void flipVertical(char * source, int srcWidth, int srcHeight, char * destination,
+static __inline__ void flipVertical(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination,
         int dstWidth __unused, int dstHeight __unused) {
     //Vertical
     size_t cpy_bytes = sizeof(char) * 4;
@@ -34,8 +34,8 @@
     }
 }
 
-static __inline__ void flipHorizontal(char * source, int srcWidth, int srcHeight,
-        char * destination, int dstWidth __unused, int dstHeight __unused) {
+static __inline__ void flipHorizontal(uint8_t * source, int srcWidth, int srcHeight,
+        uint8_t * destination, int dstWidth __unused, int dstHeight __unused) {
     //Horizontal
     size_t cpy_bytes = sizeof(char) * 4;
     int width = cpy_bytes * srcWidth;
@@ -52,12 +52,12 @@
     }
 }
 
-static __inline__ void flip_fun(int flip, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
+static __inline__ void flip_fun(int flip, uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight){
     int horiz = (flip & 1) != 0;
     int vert = (flip & 2) != 0;
     if (horiz && vert){
         int arr_len = dstWidth * dstHeight * sizeof(char) * 4;
-        char* temp = (char *) malloc(arr_len);
+        uint8_t* temp = (uint8_t *) malloc(arr_len);
         flipHorizontal(source, srcWidth, srcHeight, temp, dstWidth, dstHeight);
         flipVertical(temp, dstWidth, dstHeight, destination, dstWidth, dstHeight);
         free(temp);
@@ -74,7 +74,7 @@
 }
 
 //90 CCW (opposite of what's used in UI?)
-static __inline__ void rotate90(char * source, int srcWidth, int srcHeight, char * destination,
+static __inline__ void rotate90(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination,
         int dstWidth __unused, int dstHeight __unused) {
     size_t cpy_bytes = sizeof(char) * 4;
     int width = cpy_bytes * srcWidth;
@@ -88,17 +88,17 @@
     }
 }
 
-static __inline__ void rotate180(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
+static __inline__ void rotate180(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight){
     flip_fun(3, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
 }
 
-static __inline__ void rotate270(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
+static __inline__ void rotate270(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight){
     rotate90(source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
     flip_fun(3, destination, dstWidth, dstHeight, destination, dstWidth, dstHeight);
 }
 
 // rotate == 1 is 90 degrees, 2 is 180, 3 is 270 (positive is CCW).
-static __inline__ void rotate_fun(int rotate, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){
+static __inline__ void rotate_fun(int rotate, uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight){
     switch( rotate )
     {
         case 1:
@@ -115,7 +115,7 @@
     }
 }
 
-static __inline__ void crop(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight){
+static __inline__ void crop(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight){
     size_t cpy_bytes = sizeof(char) * 4;
     int row_width = cpy_bytes * srcWidth;
     int new_row_width = cpy_bytes * dstWidth;
@@ -129,8 +129,8 @@
 }
 
 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) {
-    char* destination = 0;
-    char* source = 0;
+    uint8_t* destination = 0;
+    uint8_t* source = 0;
     if (srcWidth != dstWidth || srcHeight != dstHeight) {
         return;
     }
@@ -142,8 +142,8 @@
 }
 
 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint rotate) {
-    char* destination = 0;
-    char* source = 0;
+    uint8_t* destination = 0;
+    uint8_t* source = 0;
     AndroidBitmap_lockPixels(env, src, (void**) &source);
     AndroidBitmap_lockPixels(env, dst, (void**) &destination);
     rotate_fun(rotate, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
@@ -152,8 +152,8 @@
 }
 
 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) {
-    char* destination = 0;
-    char* source = 0;
+    uint8_t* destination = 0;
+    uint8_t* source = 0;
     AndroidBitmap_lockPixels(env, src, (void**) &source);
     AndroidBitmap_lockPixels(env, dst, (void**) &destination);
     crop(source, srcWidth, srcHeight, destination, dstWidth, dstHeight, offsetWidth, offsetHeight);
@@ -164,8 +164,8 @@
 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterStraighten, jobject src, jint srcWidth __unused,
         jint srcHeight __unused, jobject dst, jint dstWidth, jint dstHeight,
         jfloat straightenAngle __unused) {
-    char* destination = 0;
-    char* source = 0;
+    uint8_t* destination = 0;
+    uint8_t* source = 0;
     int len = dstWidth * dstHeight * 4;
     AndroidBitmap_lockPixels(env, src, (void**) &source);
     AndroidBitmap_lockPixels(env, dst, (void**) &destination);
diff --git a/jni/filters/saturated.c b/jni/filters/saturated.c
index f5cf767..a672a4e 100644
--- a/jni/filters/saturated.c
+++ b/jni/filters/saturated.c
@@ -18,7 +18,7 @@
 
 void JNIFUNCF(ImageFilterSaturated, nativeApplyFilter, jobject bitmap, jint width, jint height, jfloat saturation)
 {
-    char* destination = 0;
+    uint8_t* destination = 0;
     AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
     int i;
     int len = width * height * 4;
diff --git a/jni/filters/vibrance.c b/jni/filters/vibrance.c
index feef7bc..78228d1 100644
--- a/jni/filters/vibrance.c
+++ b/jni/filters/vibrance.c
@@ -19,7 +19,7 @@
 
 void JNIFUNCF(ImageFilterVibrance, nativeApplyFilter, jobject bitmap, jint width, jint height,  jfloat vibrance)
 {
-    char* destination = 0;
+    uint8_t* destination = 0;
     AndroidBitmap_lockPixels(env, bitmap, (void**) &destination);
     int i;
     int len = width * height * 4;
diff --git a/jni_jpegstream/Android.mk b/jni_jpegstream/Android.mk
index f1ea324..347e145 100644
--- a/jni_jpegstream/Android.mk
+++ b/jni_jpegstream/Android.mk
@@ -4,9 +4,7 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_MODULE        := libjni_jpegstream
-
-LOCAL_NDK_STL_VARIANT := c++_static
+LOCAL_MODULE        := libjni_gallery_jpegstream
 
 LOCAL_C_INCLUDES := $(LOCAL_PATH) \
                     $(LOCAL_PATH)/src
diff --git a/privapp_whitelist_com.android.gallery3d.xml b/privapp_whitelist_com.android.gallery3d.xml
new file mode 100644
index 0000000..2a53b90
--- /dev/null
+++ b/privapp_whitelist_com.android.gallery3d.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2019-2020 The LineageOS Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<permissions>
+    <privapp-permissions package="com.android.gallery3d">
+        <permission name="android.permission.MODIFY_AUDIO_ROUTING"/>
+    </privapp-permissions>
+</permissions>
diff --git a/proguard.flags b/proguard.flags
index 5fde2d3..21051bb 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1,6 +1,10 @@
 # Disable the warnings of using dynamic method call in common library.
 -dontnote com.android.gallery3d.common.*
 
+#Avoid the library class dependency error
+-dontwarn android.view.inputmethod.InputMethodManager
+-dontwarn android.content.res.Resources
+
 # Keep all classes extended from com.android.gallery3d.common.Entry
 # Since we annotate on the fields and use reflection to create SQL
 # according to those field.
@@ -40,16 +44,6 @@
 # Disable the warnings of using dynamic method calls in EffectsRecorder
 -dontnote com.android.camera.EffectsRecorder
 
-# Required for ActionBarSherlock
--keep class android.support.v4.app.** { *; }
--keep interface android.support.v4.app.** { *; }
--keep class com.actionbarsherlock.** { *; }
--keep interface com.actionbarsherlock.** { *; }
--keepattributes *Annotation*
-
-# Required for JobIntentService
--keep class androidx.core.app.CoreComponentFactory { *; }
-
 # Required for mp4parser
 -keep public class * implements com.coremedia.iso.boxes.Box
 
@@ -86,4 +80,6 @@
 -keep class com.android.gallery3d.jpegstream.JPEGInputStream { *; }
 -keep class com.android.gallery3d.jpegstream.StreamUtils { *; }
 
-
+-keep class com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine{
+  *;
+}
diff --git a/res/drawable-hdpi/bg_controller_indicator.9.png b/res/drawable-hdpi/bg_controller_indicator.9.png
new file mode 100644
index 0000000..e90e9f7
--- /dev/null
+++ b/res/drawable-hdpi/bg_controller_indicator.9.png
Binary files differ
diff --git a/res/drawable-hdpi/bg_vidcontrol.png b/res/drawable-hdpi/bg_vidcontrol.png
deleted file mode 100644
index dfe2da1..0000000
--- a/res/drawable-hdpi/bg_vidcontrol.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/blackboard.png b/res/drawable-hdpi/blackboard.png
new file mode 100644
index 0000000..6cb6e31
--- /dev/null
+++ b/res/drawable-hdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-hdpi/blur.png b/res/drawable-hdpi/blur.png
new file mode 100644
index 0000000..b767b1b
--- /dev/null
+++ b/res/drawable-hdpi/blur.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_help.png b/res/drawable-hdpi/btn_tp_help.png
new file mode 100644
index 0000000..77c9a57
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_help.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_help_sel.png b/res/drawable-hdpi/btn_tp_help_sel.png
new file mode 100644
index 0000000..80893dd
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_help_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_sel_bg.png b/res/drawable-hdpi/btn_tp_sel_bg.png
new file mode 100644
index 0000000..2560ec3
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_sel_bg.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_sel_bg_sel.png b/res/drawable-hdpi/btn_tp_sel_bg_sel.png
new file mode 100644
index 0000000..f2170e1
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_sel_bg_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_touchup.png b/res/drawable-hdpi/btn_tp_touchup.png
new file mode 100644
index 0000000..cd450a7
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_touchup.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_touchup_sel.png b/res/drawable-hdpi/btn_tp_touchup_sel.png
new file mode 100644
index 0000000..6b8f18c
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_touchup_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_undo.png b/res/drawable-hdpi/btn_tp_undo.png
new file mode 100644
index 0000000..de3edd1
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_undo.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_undo_disabled.png b/res/drawable-hdpi/btn_tp_undo_disabled.png
new file mode 100644
index 0000000..e45d761
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_undo_disabled.png
Binary files differ
diff --git a/res/drawable-hdpi/btn_tp_undo_sel.png b/res/drawable-hdpi/btn_tp_undo_sel.png
new file mode 100644
index 0000000..1d2e5ae
--- /dev/null
+++ b/res/drawable-hdpi/btn_tp_undo_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/bw.png b/res/drawable-hdpi/bw.png
new file mode 100644
index 0000000..fa81754
--- /dev/null
+++ b/res/drawable-hdpi/bw.png
Binary files differ
diff --git a/res/drawable-hdpi/drawer_bg.png b/res/drawable-hdpi/drawer_bg.png
new file mode 100644
index 0000000..d7dd7a6
--- /dev/null
+++ b/res/drawable-hdpi/drawer_bg.png
Binary files differ
diff --git a/res/drawable-hdpi/drm_image.png b/res/drawable-hdpi/drm_image.png
new file mode 100644
index 0000000..f51d615
--- /dev/null
+++ b/res/drawable-hdpi/drm_image.png
Binary files differ
diff --git a/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png b/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png
deleted file mode 100644
index 06e5b47..0000000
--- a/res/drawable-hdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/feather.png b/res/drawable-hdpi/feather.png
new file mode 100644
index 0000000..02bd370
--- /dev/null
+++ b/res/drawable-hdpi/feather.png
Binary files differ
diff --git a/res/drawable-hdpi/filtershow_dualcam_focus.png b/res/drawable-hdpi/filtershow_dualcam_focus.png
new file mode 100644
index 0000000..d1d92c1
--- /dev/null
+++ b/res/drawable-hdpi/filtershow_dualcam_focus.png
Binary files differ
diff --git a/res/drawable-hdpi/filtershow_dualcam_fusion.png b/res/drawable-hdpi/filtershow_dualcam_fusion.png
new file mode 100644
index 0000000..344ce25
--- /dev/null
+++ b/res/drawable-hdpi/filtershow_dualcam_fusion.png
Binary files differ
diff --git a/res/drawable-hdpi/filtershow_dualcam_halo.png b/res/drawable-hdpi/filtershow_dualcam_halo.png
new file mode 100644
index 0000000..cd4359b
--- /dev/null
+++ b/res/drawable-hdpi/filtershow_dualcam_halo.png
Binary files differ
diff --git a/res/drawable-hdpi/filtershow_dualcam_sketch.png b/res/drawable-hdpi/filtershow_dualcam_sketch.png
new file mode 100644
index 0000000..f04db3e
--- /dev/null
+++ b/res/drawable-hdpi/filtershow_dualcam_sketch.png
Binary files differ
diff --git a/res/drawable-hdpi/focus.png b/res/drawable-hdpi/focus.png
new file mode 100644
index 0000000..a168a05
--- /dev/null
+++ b/res/drawable-hdpi/focus.png
Binary files differ
diff --git a/res/drawable-hdpi/fusion.png b/res/drawable-hdpi/fusion.png
new file mode 100644
index 0000000..7abeb24
--- /dev/null
+++ b/res/drawable-hdpi/fusion.png
Binary files differ
diff --git a/res/drawable-hdpi/halo.png b/res/drawable-hdpi/halo.png
new file mode 100644
index 0000000..f32da85
--- /dev/null
+++ b/res/drawable-hdpi/halo.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_large.png b/res/drawable-hdpi/ic_brush_size_large.png
new file mode 100644
index 0000000..e67f63d
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_large.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_large_sel.png b/res/drawable-hdpi/ic_brush_size_large_sel.png
new file mode 100644
index 0000000..c787f87
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_large_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_med.png b/res/drawable-hdpi/ic_brush_size_med.png
new file mode 100644
index 0000000..7dc3cd1
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_med.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_med_sel.png b/res/drawable-hdpi/ic_brush_size_med_sel.png
new file mode 100644
index 0000000..71b5218
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_med_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_sm.png b/res/drawable-hdpi/ic_brush_size_sm.png
new file mode 100644
index 0000000..afb6917
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_sm.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_brush_size_sm_sel.png b/res/drawable-hdpi/ic_brush_size_sm_sel.png
new file mode 100644
index 0000000..12601ed
--- /dev/null
+++ b/res/drawable-hdpi/ic_brush_size_sm_sel.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_display_bookmark.png b/res/drawable-hdpi/ic_menu_display_bookmark.png
new file mode 100644
index 0000000..a5118ea
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_loop.png b/res/drawable-hdpi/ic_menu_loop.png
new file mode 100644
index 0000000..add4633
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_loop.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_unloop.png b/res/drawable-hdpi/ic_menu_unloop.png
new file mode 100644
index 0000000..3140051
--- /dev/null
+++ b/res/drawable-hdpi/ic_menu_unloop.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_photoeditor_dualcam.png b/res/drawable-hdpi/ic_photoeditor_dualcam.png
new file mode 100644
index 0000000..f3227f1
--- /dev/null
+++ b/res/drawable-hdpi/ic_photoeditor_dualcam.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_photoeditor_makeup.png b/res/drawable-hdpi/ic_photoeditor_makeup.png
new file mode 100644
index 0000000..06913d6
--- /dev/null
+++ b/res/drawable-hdpi/ic_photoeditor_makeup.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_separator_line.png b/res/drawable-hdpi/ic_separator_line.png
new file mode 100644
index 0000000..2ebff3f
--- /dev/null
+++ b/res/drawable-hdpi/ic_separator_line.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_bokeh.png b/res/drawable-hdpi/ic_tp_bokeh.png
new file mode 100644
index 0000000..c63cf48
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_bokeh.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_fusion.png b/res/drawable-hdpi/ic_tp_fusion.png
new file mode 100644
index 0000000..8df5c0c
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_fusion.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_halo.png b/res/drawable-hdpi/ic_tp_halo.png
new file mode 100644
index 0000000..5754b1b
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_halo.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_motion_blur.png b/res/drawable-hdpi/ic_tp_motion_blur.png
new file mode 100644
index 0000000..be21d3c
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_motion_blur.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_normal.png b/res/drawable-hdpi/ic_tp_normal.png
new file mode 100644
index 0000000..f33eb20
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tp_sketch.png b/res/drawable-hdpi/ic_tp_sketch.png
new file mode 100644
index 0000000..10aa560
--- /dev/null
+++ b/res/drawable-hdpi/ic_tp_sketch.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ts_makeup_bigeye.png b/res/drawable-hdpi/ic_ts_makeup_bigeye.png
new file mode 100644
index 0000000..bf7b6f5
--- /dev/null
+++ b/res/drawable-hdpi/ic_ts_makeup_bigeye.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ts_makeup_soften.png b/res/drawable-hdpi/ic_ts_makeup_soften.png
new file mode 100644
index 0000000..caa6451
--- /dev/null
+++ b/res/drawable-hdpi/ic_ts_makeup_soften.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ts_makeup_trimface.png b/res/drawable-hdpi/ic_ts_makeup_trimface.png
new file mode 100644
index 0000000..3ac43f7
--- /dev/null
+++ b/res/drawable-hdpi/ic_ts_makeup_trimface.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_ts_makeup_whiten.png b/res/drawable-hdpi/ic_ts_makeup_whiten.png
new file mode 100644
index 0000000..a12560f
--- /dev/null
+++ b/res/drawable-hdpi/ic_ts_makeup_whiten.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_disable_pause.png b/res/drawable-hdpi/ic_vidcontrol_disable_pause.png
new file mode 100644
index 0000000..41b3725
--- /dev/null
+++ b/res/drawable-hdpi/ic_vidcontrol_disable_pause.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_disable_play.png b/res/drawable-hdpi/ic_vidcontrol_disable_play.png
new file mode 100644
index 0000000..fdc5380
--- /dev/null
+++ b/res/drawable-hdpi/ic_vidcontrol_disable_play.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_disable_reload.png b/res/drawable-hdpi/ic_vidcontrol_disable_reload.png
new file mode 100644
index 0000000..5611a92
--- /dev/null
+++ b/res/drawable-hdpi/ic_vidcontrol_disable_reload.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_pause.png b/res/drawable-hdpi/ic_vidcontrol_pause.png
deleted file mode 100644
index 3d1a8bf..0000000
--- a/res/drawable-hdpi/ic_vidcontrol_pause.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_play.png b/res/drawable-hdpi/ic_vidcontrol_play.png
deleted file mode 100644
index cc02166..0000000
--- a/res/drawable-hdpi/ic_vidcontrol_play.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/ic_vidcontrol_reload.png b/res/drawable-hdpi/ic_vidcontrol_reload.png
deleted file mode 100644
index bf8d529..0000000
--- a/res/drawable-hdpi/ic_vidcontrol_reload.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/media_default_bkg.9.png b/res/drawable-hdpi/media_default_bkg.9.png
new file mode 100644
index 0000000..7b95239
--- /dev/null
+++ b/res/drawable-hdpi/media_default_bkg.9.png
Binary files differ
diff --git a/res/drawable-hdpi/motion.png b/res/drawable-hdpi/motion.png
new file mode 100644
index 0000000..1a03479
--- /dev/null
+++ b/res/drawable-hdpi/motion.png
Binary files differ
diff --git a/res/drawable-hdpi/multiselect.png b/res/drawable-hdpi/multiselect.png
new file mode 100644
index 0000000..59c8eee
--- /dev/null
+++ b/res/drawable-hdpi/multiselect.png
Binary files differ
diff --git a/res/drawable-hdpi/negative.png b/res/drawable-hdpi/negative.png
new file mode 100644
index 0000000..b4989d4
--- /dev/null
+++ b/res/drawable-hdpi/negative.png
Binary files differ
diff --git a/res/drawable-hdpi/none.png b/res/drawable-hdpi/none.png
new file mode 100644
index 0000000..58a7fd8
--- /dev/null
+++ b/res/drawable-hdpi/none.png
Binary files differ
diff --git a/res/drawable-hdpi/play_detail.png b/res/drawable-hdpi/play_detail.png
new file mode 100644
index 0000000..21060fc
--- /dev/null
+++ b/res/drawable-hdpi/play_detail.png
Binary files differ
diff --git a/res/drawable-hdpi/posterize.png b/res/drawable-hdpi/posterize.png
new file mode 100644
index 0000000..042b686
--- /dev/null
+++ b/res/drawable-hdpi/posterize.png
Binary files differ
diff --git a/res/drawable-hdpi/random.png b/res/drawable-hdpi/random.png
new file mode 100644
index 0000000..3ae23df
--- /dev/null
+++ b/res/drawable-hdpi/random.png
Binary files differ
diff --git a/res/drawable-hdpi/rectangle.png b/res/drawable-hdpi/rectangle.png
new file mode 100644
index 0000000..10c0e9a
--- /dev/null
+++ b/res/drawable-hdpi/rectangle.png
Binary files differ
diff --git a/res/drawable-hdpi/round.png b/res/drawable-hdpi/round.png
new file mode 100644
index 0000000..d9014c0
--- /dev/null
+++ b/res/drawable-hdpi/round.png
Binary files differ
diff --git a/res/drawable-hdpi/scrubber_knob.png b/res/drawable-hdpi/scrubber_knob.png
index 426e3da..817fd3a 100644
--- a/res/drawable-hdpi/scrubber_knob.png
+++ b/res/drawable-hdpi/scrubber_knob.png
Binary files differ
diff --git a/res/drawable-hdpi/sketch.png b/res/drawable-hdpi/sketch.png
new file mode 100644
index 0000000..f43f6ac
--- /dev/null
+++ b/res/drawable-hdpi/sketch.png
Binary files differ
diff --git a/res/drawable-hdpi/square.png b/res/drawable-hdpi/square.png
new file mode 100644
index 0000000..9b744ba
--- /dev/null
+++ b/res/drawable-hdpi/square.png
Binary files differ
diff --git a/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png b/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
deleted file mode 100644
index 9c5147e..0000000
--- a/res/drawable-hdpi/switch_thumb_activated_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/text_select_handle_left.png b/res/drawable-hdpi/text_select_handle_left.png
index d2ed06d..abefa9e 100644
--- a/res/drawable-hdpi/text_select_handle_left.png
+++ b/res/drawable-hdpi/text_select_handle_left.png
Binary files differ
diff --git a/res/drawable-hdpi/text_select_handle_right.png b/res/drawable-hdpi/text_select_handle_right.png
index e419249..5679a17 100644
--- a/res/drawable-hdpi/text_select_handle_right.png
+++ b/res/drawable-hdpi/text_select_handle_right.png
Binary files differ
diff --git a/res/drawable-hdpi/trueportrait.png b/res/drawable-hdpi/trueportrait.png
new file mode 100644
index 0000000..902ffaf
--- /dev/null
+++ b/res/drawable-hdpi/trueportrait.png
Binary files differ
diff --git a/res/drawable-hdpi/trueportrait_disabled.png b/res/drawable-hdpi/trueportrait_disabled.png
new file mode 100644
index 0000000..8708a24
--- /dev/null
+++ b/res/drawable-hdpi/trueportrait_disabled.png
Binary files differ
diff --git a/res/drawable-hdpi/trueportrait_select.png b/res/drawable-hdpi/trueportrait_select.png
new file mode 100644
index 0000000..6c2e8dd
--- /dev/null
+++ b/res/drawable-hdpi/trueportrait_select.png
Binary files differ
diff --git a/res/drawable-hdpi/whiteboard.png b/res/drawable-hdpi/whiteboard.png
new file mode 100644
index 0000000..584da40
--- /dev/null
+++ b/res/drawable-hdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-hdpi/zoom.png b/res/drawable-hdpi/zoom.png
new file mode 100644
index 0000000..ea1211f
--- /dev/null
+++ b/res/drawable-hdpi/zoom.png
Binary files differ
diff --git a/res/drawable-mdpi/bg_vidcontrol.png b/res/drawable-mdpi/bg_vidcontrol.png
deleted file mode 100644
index 5a5ce55..0000000
--- a/res/drawable-mdpi/bg_vidcontrol.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/drm_image.png b/res/drawable-mdpi/drm_image.png
new file mode 100644
index 0000000..dbbd7d8
--- /dev/null
+++ b/res/drawable-mdpi/drm_image.png
Binary files differ
diff --git a/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png b/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png
deleted file mode 100644
index 81de1bb..0000000
--- a/res/drawable-mdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/filtershow_dualcam_focus.png b/res/drawable-mdpi/filtershow_dualcam_focus.png
new file mode 100644
index 0000000..b06d702
--- /dev/null
+++ b/res/drawable-mdpi/filtershow_dualcam_focus.png
Binary files differ
diff --git a/res/drawable-mdpi/filtershow_dualcam_fusion.png b/res/drawable-mdpi/filtershow_dualcam_fusion.png
new file mode 100644
index 0000000..3be06b9
--- /dev/null
+++ b/res/drawable-mdpi/filtershow_dualcam_fusion.png
Binary files differ
diff --git a/res/drawable-mdpi/filtershow_dualcam_halo.png b/res/drawable-mdpi/filtershow_dualcam_halo.png
new file mode 100644
index 0000000..9f36921
--- /dev/null
+++ b/res/drawable-mdpi/filtershow_dualcam_halo.png
Binary files differ
diff --git a/res/drawable-mdpi/filtershow_dualcam_sketch.png b/res/drawable-mdpi/filtershow_dualcam_sketch.png
new file mode 100644
index 0000000..5dc2c19
--- /dev/null
+++ b/res/drawable-mdpi/filtershow_dualcam_sketch.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_display_bookmark.png b/res/drawable-mdpi/ic_menu_display_bookmark.png
new file mode 100644
index 0000000..a3acdd6
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_loop.png b/res/drawable-mdpi/ic_menu_loop.png
new file mode 100644
index 0000000..688b2c5
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_loop.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_single_track.png b/res/drawable-mdpi/ic_menu_single_track.png
new file mode 100755
index 0000000..b11c2e4
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_single_track.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_stereo.png b/res/drawable-mdpi/ic_menu_stereo.png
new file mode 100755
index 0000000..ef3ee9f
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_stereo.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_unloop.png b/res/drawable-mdpi/ic_menu_unloop.png
new file mode 100644
index 0000000..e474964
--- /dev/null
+++ b/res/drawable-mdpi/ic_menu_unloop.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_photoeditor_dualcam.png b/res/drawable-mdpi/ic_photoeditor_dualcam.png
new file mode 100644
index 0000000..6b05972
--- /dev/null
+++ b/res/drawable-mdpi/ic_photoeditor_dualcam.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_photoeditor_makeup.png b/res/drawable-mdpi/ic_photoeditor_makeup.png
new file mode 100644
index 0000000..606f591
--- /dev/null
+++ b/res/drawable-mdpi/ic_photoeditor_makeup.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ts_makeup_bigeye.png b/res/drawable-mdpi/ic_ts_makeup_bigeye.png
new file mode 100644
index 0000000..8d8da29
--- /dev/null
+++ b/res/drawable-mdpi/ic_ts_makeup_bigeye.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ts_makeup_soften.png b/res/drawable-mdpi/ic_ts_makeup_soften.png
new file mode 100644
index 0000000..a36d189
--- /dev/null
+++ b/res/drawable-mdpi/ic_ts_makeup_soften.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ts_makeup_trimface.png b/res/drawable-mdpi/ic_ts_makeup_trimface.png
new file mode 100644
index 0000000..e27370f
--- /dev/null
+++ b/res/drawable-mdpi/ic_ts_makeup_trimface.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_ts_makeup_whiten.png b/res/drawable-mdpi/ic_ts_makeup_whiten.png
new file mode 100644
index 0000000..7ac8823
--- /dev/null
+++ b/res/drawable-mdpi/ic_ts_makeup_whiten.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_disable_pause.png b/res/drawable-mdpi/ic_vidcontrol_disable_pause.png
new file mode 100644
index 0000000..c5c42cb
--- /dev/null
+++ b/res/drawable-mdpi/ic_vidcontrol_disable_pause.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_disable_play.png b/res/drawable-mdpi/ic_vidcontrol_disable_play.png
new file mode 100644
index 0000000..70374fb
--- /dev/null
+++ b/res/drawable-mdpi/ic_vidcontrol_disable_play.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_disable_reload.png b/res/drawable-mdpi/ic_vidcontrol_disable_reload.png
new file mode 100644
index 0000000..052df4c
--- /dev/null
+++ b/res/drawable-mdpi/ic_vidcontrol_disable_reload.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_pause.png b/res/drawable-mdpi/ic_vidcontrol_pause.png
deleted file mode 100644
index 9319079..0000000
--- a/res/drawable-mdpi/ic_vidcontrol_pause.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_play.png b/res/drawable-mdpi/ic_vidcontrol_play.png
deleted file mode 100644
index 8d7cd83..0000000
--- a/res/drawable-mdpi/ic_vidcontrol_play.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/ic_vidcontrol_reload.png b/res/drawable-mdpi/ic_vidcontrol_reload.png
deleted file mode 100644
index 51b1f48..0000000
--- a/res/drawable-mdpi/ic_vidcontrol_reload.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/media_default_bkg.9.png b/res/drawable-mdpi/media_default_bkg.9.png
new file mode 100644
index 0000000..20bb108
--- /dev/null
+++ b/res/drawable-mdpi/media_default_bkg.9.png
Binary files differ
diff --git a/res/drawable-mdpi/scrubber_knob.png b/res/drawable-mdpi/scrubber_knob.png
index 9205d9c..43d1b3f 100644
--- a/res/drawable-mdpi/scrubber_knob.png
+++ b/res/drawable-mdpi/scrubber_knob.png
Binary files differ
diff --git a/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png b/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
deleted file mode 100644
index 3d7c236..0000000
--- a/res/drawable-mdpi/switch_thumb_activated_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/text_select_handle_left.png b/res/drawable-mdpi/text_select_handle_left.png
index 750cdea..2ef6f7c 100644
--- a/res/drawable-mdpi/text_select_handle_left.png
+++ b/res/drawable-mdpi/text_select_handle_left.png
Binary files differ
diff --git a/res/drawable-mdpi/text_select_handle_right.png b/res/drawable-mdpi/text_select_handle_right.png
index fc3d144..9e426c7 100644
--- a/res/drawable-mdpi/text_select_handle_right.png
+++ b/res/drawable-mdpi/text_select_handle_right.png
Binary files differ
diff --git a/res/drawable-sw600dp/bg_vidcontrol.png b/res/drawable-sw600dp/bg_vidcontrol.png
deleted file mode 100644
index dfe2da1..0000000
--- a/res/drawable-sw600dp/bg_vidcontrol.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_disable_pause.png b/res/drawable-sw600dp/ic_vidcontrol_disable_pause.png
new file mode 100644
index 0000000..41b3725
--- /dev/null
+++ b/res/drawable-sw600dp/ic_vidcontrol_disable_pause.png
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_disable_play.png b/res/drawable-sw600dp/ic_vidcontrol_disable_play.png
new file mode 100644
index 0000000..fdc5380
--- /dev/null
+++ b/res/drawable-sw600dp/ic_vidcontrol_disable_play.png
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_disable_reload.png b/res/drawable-sw600dp/ic_vidcontrol_disable_reload.png
new file mode 100644
index 0000000..5611a92
--- /dev/null
+++ b/res/drawable-sw600dp/ic_vidcontrol_disable_reload.png
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_pause.png b/res/drawable-sw600dp/ic_vidcontrol_pause.png
deleted file mode 100644
index 3d1a8bf..0000000
--- a/res/drawable-sw600dp/ic_vidcontrol_pause.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_play.png b/res/drawable-sw600dp/ic_vidcontrol_play.png
deleted file mode 100644
index cc02166..0000000
--- a/res/drawable-sw600dp/ic_vidcontrol_play.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp/ic_vidcontrol_reload.png b/res/drawable-sw600dp/ic_vidcontrol_reload.png
deleted file mode 100644
index bf8d529..0000000
--- a/res/drawable-sw600dp/ic_vidcontrol_reload.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-sw600dp/scrubber_knob.png b/res/drawable-sw600dp/scrubber_knob.png
index 426e3da..817fd3a 100644
--- a/res/drawable-sw600dp/scrubber_knob.png
+++ b/res/drawable-sw600dp/scrubber_knob.png
Binary files differ
diff --git a/res/drawable-xhdpi/bg_controller_indicator.9.png b/res/drawable-xhdpi/bg_controller_indicator.9.png
new file mode 100644
index 0000000..203a93b
--- /dev/null
+++ b/res/drawable-xhdpi/bg_controller_indicator.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/bg_vidcontrol.png b/res/drawable-xhdpi/bg_vidcontrol.png
deleted file mode 100644
index 0eb8148..0000000
--- a/res/drawable-xhdpi/bg_vidcontrol.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/blackboard.png b/res/drawable-xhdpi/blackboard.png
new file mode 100644
index 0000000..287a6f7
--- /dev/null
+++ b/res/drawable-xhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/blur.png b/res/drawable-xhdpi/blur.png
new file mode 100644
index 0000000..279848e
--- /dev/null
+++ b/res/drawable-xhdpi/blur.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_help.png b/res/drawable-xhdpi/btn_tp_help.png
new file mode 100644
index 0000000..c8bee80
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_help.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_help_sel.png b/res/drawable-xhdpi/btn_tp_help_sel.png
new file mode 100644
index 0000000..b5c70a6
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_help_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_sel_bg.png b/res/drawable-xhdpi/btn_tp_sel_bg.png
new file mode 100644
index 0000000..a905e64
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_sel_bg.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_sel_bg_sel.png b/res/drawable-xhdpi/btn_tp_sel_bg_sel.png
new file mode 100644
index 0000000..cdad80b
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_sel_bg_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_touchup.png b/res/drawable-xhdpi/btn_tp_touchup.png
new file mode 100644
index 0000000..764042c
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_touchup.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_touchup_sel.png b/res/drawable-xhdpi/btn_tp_touchup_sel.png
new file mode 100644
index 0000000..93f9ef3
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_touchup_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_undo.png b/res/drawable-xhdpi/btn_tp_undo.png
new file mode 100644
index 0000000..6cb1171
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_undo.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_undo_disabled.png b/res/drawable-xhdpi/btn_tp_undo_disabled.png
new file mode 100644
index 0000000..937957e
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_undo_disabled.png
Binary files differ
diff --git a/res/drawable-xhdpi/btn_tp_undo_sel.png b/res/drawable-xhdpi/btn_tp_undo_sel.png
new file mode 100644
index 0000000..c5ef8e7
--- /dev/null
+++ b/res/drawable-xhdpi/btn_tp_undo_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/bw.png b/res/drawable-xhdpi/bw.png
new file mode 100644
index 0000000..d0052d1
--- /dev/null
+++ b/res/drawable-xhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xhdpi/drawer_bg.png b/res/drawable-xhdpi/drawer_bg.png
new file mode 100644
index 0000000..5640493
--- /dev/null
+++ b/res/drawable-xhdpi/drawer_bg.png
Binary files differ
diff --git a/res/drawable-xhdpi/drm_image.png b/res/drawable-xhdpi/drm_image.png
new file mode 100644
index 0000000..ff28776
--- /dev/null
+++ b/res/drawable-xhdpi/drm_image.png
Binary files differ
diff --git a/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png b/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png
deleted file mode 100644
index 36d8cf4..0000000
--- a/res/drawable-xhdpi/dropdown_ic_arrow_normal_holo_dark.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/feather.png b/res/drawable-xhdpi/feather.png
new file mode 100644
index 0000000..d622a2f
--- /dev/null
+++ b/res/drawable-xhdpi/feather.png
Binary files differ
diff --git a/res/drawable-xhdpi/filtershow_dualcam_focus.png b/res/drawable-xhdpi/filtershow_dualcam_focus.png
new file mode 100644
index 0000000..9d972d3
--- /dev/null
+++ b/res/drawable-xhdpi/filtershow_dualcam_focus.png
Binary files differ
diff --git a/res/drawable-xhdpi/filtershow_dualcam_fusion.png b/res/drawable-xhdpi/filtershow_dualcam_fusion.png
new file mode 100644
index 0000000..747c7e2
--- /dev/null
+++ b/res/drawable-xhdpi/filtershow_dualcam_fusion.png
Binary files differ
diff --git a/res/drawable-xhdpi/filtershow_dualcam_halo.png b/res/drawable-xhdpi/filtershow_dualcam_halo.png
new file mode 100644
index 0000000..c62e5ef
--- /dev/null
+++ b/res/drawable-xhdpi/filtershow_dualcam_halo.png
Binary files differ
diff --git a/res/drawable-xhdpi/filtershow_dualcam_sketch.png b/res/drawable-xhdpi/filtershow_dualcam_sketch.png
new file mode 100644
index 0000000..8eb72b1
--- /dev/null
+++ b/res/drawable-xhdpi/filtershow_dualcam_sketch.png
Binary files differ
diff --git a/res/drawable-xhdpi/focus.png b/res/drawable-xhdpi/focus.png
new file mode 100644
index 0000000..ea695b4
--- /dev/null
+++ b/res/drawable-xhdpi/focus.png
Binary files differ
diff --git a/res/drawable-xhdpi/fusion.png b/res/drawable-xhdpi/fusion.png
new file mode 100644
index 0000000..158fcbb
--- /dev/null
+++ b/res/drawable-xhdpi/fusion.png
Binary files differ
diff --git a/res/drawable-xhdpi/halo.png b/res/drawable-xhdpi/halo.png
new file mode 100644
index 0000000..8047a73
--- /dev/null
+++ b/res/drawable-xhdpi/halo.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_large.png b/res/drawable-xhdpi/ic_brush_size_large.png
new file mode 100644
index 0000000..4bd4db7
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_large.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_large_sel.png b/res/drawable-xhdpi/ic_brush_size_large_sel.png
new file mode 100644
index 0000000..c96e76b
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_large_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_med.png b/res/drawable-xhdpi/ic_brush_size_med.png
new file mode 100644
index 0000000..37a0f6a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_med.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_med_sel.png b/res/drawable-xhdpi/ic_brush_size_med_sel.png
new file mode 100644
index 0000000..44da98a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_med_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_sm.png b/res/drawable-xhdpi/ic_brush_size_sm.png
new file mode 100644
index 0000000..d46aba3
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_sm.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_brush_size_sm_sel.png b/res/drawable-xhdpi/ic_brush_size_sm_sel.png
new file mode 100644
index 0000000..95fc198
--- /dev/null
+++ b/res/drawable-xhdpi/ic_brush_size_sm_sel.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_display_bookmark.png b/res/drawable-xhdpi/ic_menu_display_bookmark.png
new file mode 100644
index 0000000..4ad8414
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_display_bookmark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_loop.png b/res/drawable-xhdpi/ic_menu_loop.png
new file mode 100644
index 0000000..e664915
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_loop.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_unloop.png b/res/drawable-xhdpi/ic_menu_unloop.png
new file mode 100644
index 0000000..89d1da2
--- /dev/null
+++ b/res/drawable-xhdpi/ic_menu_unloop.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_photoeditor_dualcam.png b/res/drawable-xhdpi/ic_photoeditor_dualcam.png
new file mode 100644
index 0000000..663df2f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_photoeditor_dualcam.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_photoeditor_makeup.png b/res/drawable-xhdpi/ic_photoeditor_makeup.png
new file mode 100644
index 0000000..834c899
--- /dev/null
+++ b/res/drawable-xhdpi/ic_photoeditor_makeup.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_bokeh.png b/res/drawable-xhdpi/ic_tp_bokeh.png
new file mode 100644
index 0000000..b1d9cc9
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_bokeh.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_fusion.png b/res/drawable-xhdpi/ic_tp_fusion.png
new file mode 100644
index 0000000..075eaaf
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_fusion.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_halo.png b/res/drawable-xhdpi/ic_tp_halo.png
new file mode 100644
index 0000000..30eb7d9
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_halo.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_motion_blur.png b/res/drawable-xhdpi/ic_tp_motion_blur.png
new file mode 100644
index 0000000..ba0e173
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_motion_blur.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_normal.png b/res/drawable-xhdpi/ic_tp_normal.png
new file mode 100644
index 0000000..de667bf
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_normal.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tp_sketch.png b/res/drawable-xhdpi/ic_tp_sketch.png
new file mode 100644
index 0000000..fa01434
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tp_sketch.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ts_makeup_bigeye.png b/res/drawable-xhdpi/ic_ts_makeup_bigeye.png
new file mode 100644
index 0000000..f4b8500
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ts_makeup_bigeye.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ts_makeup_soften.png b/res/drawable-xhdpi/ic_ts_makeup_soften.png
new file mode 100644
index 0000000..cdd6995
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ts_makeup_soften.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ts_makeup_trimface.png b/res/drawable-xhdpi/ic_ts_makeup_trimface.png
new file mode 100644
index 0000000..e419c19
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ts_makeup_trimface.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_ts_makeup_whiten.png b/res/drawable-xhdpi/ic_ts_makeup_whiten.png
new file mode 100644
index 0000000..6fc305f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_ts_makeup_whiten.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_disable_pause.png b/res/drawable-xhdpi/ic_vidcontrol_disable_pause.png
new file mode 100644
index 0000000..0b1a136
--- /dev/null
+++ b/res/drawable-xhdpi/ic_vidcontrol_disable_pause.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_disable_play.png b/res/drawable-xhdpi/ic_vidcontrol_disable_play.png
new file mode 100644
index 0000000..f2c2f11
--- /dev/null
+++ b/res/drawable-xhdpi/ic_vidcontrol_disable_play.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_disable_reload.png b/res/drawable-xhdpi/ic_vidcontrol_disable_reload.png
new file mode 100644
index 0000000..37a394f
--- /dev/null
+++ b/res/drawable-xhdpi/ic_vidcontrol_disable_reload.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_pause.png b/res/drawable-xhdpi/ic_vidcontrol_pause.png
deleted file mode 100644
index 4d274c0..0000000
--- a/res/drawable-xhdpi/ic_vidcontrol_pause.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_play.png b/res/drawable-xhdpi/ic_vidcontrol_play.png
deleted file mode 100644
index 6f97a64..0000000
--- a/res/drawable-xhdpi/ic_vidcontrol_play.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_vidcontrol_reload.png b/res/drawable-xhdpi/ic_vidcontrol_reload.png
deleted file mode 100644
index 2aaf491..0000000
--- a/res/drawable-xhdpi/ic_vidcontrol_reload.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/motion.png b/res/drawable-xhdpi/motion.png
new file mode 100644
index 0000000..7d2b8a6
--- /dev/null
+++ b/res/drawable-xhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xhdpi/multiselect.png b/res/drawable-xhdpi/multiselect.png
new file mode 100644
index 0000000..41ecb89
--- /dev/null
+++ b/res/drawable-xhdpi/multiselect.png
Binary files differ
diff --git a/res/drawable-xhdpi/negative.png b/res/drawable-xhdpi/negative.png
new file mode 100644
index 0000000..a1eab0d
--- /dev/null
+++ b/res/drawable-xhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xhdpi/none.png b/res/drawable-xhdpi/none.png
new file mode 100644
index 0000000..7035562
--- /dev/null
+++ b/res/drawable-xhdpi/none.png
Binary files differ
diff --git a/res/drawable-xhdpi/normal.png b/res/drawable-xhdpi/normal.png
new file mode 100644
index 0000000..91cb739
--- /dev/null
+++ b/res/drawable-xhdpi/normal.png
Binary files differ
diff --git a/res/drawable-xhdpi/play_detail.png b/res/drawable-xhdpi/play_detail.png
new file mode 100644
index 0000000..d8999dc
--- /dev/null
+++ b/res/drawable-xhdpi/play_detail.png
Binary files differ
diff --git a/res/drawable-xhdpi/posterize.png b/res/drawable-xhdpi/posterize.png
new file mode 100644
index 0000000..157ad30
--- /dev/null
+++ b/res/drawable-xhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xhdpi/random.png b/res/drawable-xhdpi/random.png
new file mode 100644
index 0000000..ca6b3f2
--- /dev/null
+++ b/res/drawable-xhdpi/random.png
Binary files differ
diff --git a/res/drawable-xhdpi/rectangle.png b/res/drawable-xhdpi/rectangle.png
new file mode 100644
index 0000000..138d25b
--- /dev/null
+++ b/res/drawable-xhdpi/rectangle.png
Binary files differ
diff --git a/res/drawable-xhdpi/round.png b/res/drawable-xhdpi/round.png
new file mode 100644
index 0000000..012a706
--- /dev/null
+++ b/res/drawable-xhdpi/round.png
Binary files differ
diff --git a/res/drawable-xhdpi/scrubber_knob.png b/res/drawable-xhdpi/scrubber_knob.png
index 4e415a2..225488e 100644
--- a/res/drawable-xhdpi/scrubber_knob.png
+++ b/res/drawable-xhdpi/scrubber_knob.png
Binary files differ
diff --git a/res/drawable-xhdpi/sketch.png b/res/drawable-xhdpi/sketch.png
new file mode 100644
index 0000000..357cb41
--- /dev/null
+++ b/res/drawable-xhdpi/sketch.png
Binary files differ
diff --git a/res/drawable-xhdpi/square.png b/res/drawable-xhdpi/square.png
new file mode 100644
index 0000000..d9d7946
--- /dev/null
+++ b/res/drawable-xhdpi/square.png
Binary files differ
diff --git a/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png b/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
deleted file mode 100644
index ca48bd8..0000000
--- a/res/drawable-xhdpi/switch_thumb_activated_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/text_select_handle_left.png b/res/drawable-xhdpi/text_select_handle_left.png
index 98d10c9..cfa3bb0 100644
--- a/res/drawable-xhdpi/text_select_handle_left.png
+++ b/res/drawable-xhdpi/text_select_handle_left.png
Binary files differ
diff --git a/res/drawable-xhdpi/text_select_handle_right.png b/res/drawable-xhdpi/text_select_handle_right.png
index b3a0c9f..90c8869 100644
--- a/res/drawable-xhdpi/text_select_handle_right.png
+++ b/res/drawable-xhdpi/text_select_handle_right.png
Binary files differ
diff --git a/res/drawable-xhdpi/three_d.png b/res/drawable-xhdpi/three_d.png
new file mode 100644
index 0000000..ab8d4df
--- /dev/null
+++ b/res/drawable-xhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xhdpi/trueportrait.png b/res/drawable-xhdpi/trueportrait.png
new file mode 100644
index 0000000..17f1ba4
--- /dev/null
+++ b/res/drawable-xhdpi/trueportrait.png
Binary files differ
diff --git a/res/drawable-xhdpi/trueportrait_disabled.png b/res/drawable-xhdpi/trueportrait_disabled.png
new file mode 100644
index 0000000..c0858e1
--- /dev/null
+++ b/res/drawable-xhdpi/trueportrait_disabled.png
Binary files differ
diff --git a/res/drawable-xhdpi/trueportrait_select.png b/res/drawable-xhdpi/trueportrait_select.png
new file mode 100644
index 0000000..a334b2a
--- /dev/null
+++ b/res/drawable-xhdpi/trueportrait_select.png
Binary files differ
diff --git a/res/drawable-xhdpi/whiteboard.png b/res/drawable-xhdpi/whiteboard.png
new file mode 100644
index 0000000..1225d33
--- /dev/null
+++ b/res/drawable-xhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xhdpi/zoom.png b/res/drawable-xhdpi/zoom.png
new file mode 100644
index 0000000..f3eac3d7
--- /dev/null
+++ b/res/drawable-xhdpi/zoom.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bg_controller_indicator.9.png b/res/drawable-xxhdpi/bg_controller_indicator.9.png
new file mode 100644
index 0000000..093f136
--- /dev/null
+++ b/res/drawable-xxhdpi/bg_controller_indicator.9.png
Binary files differ
diff --git a/res/drawable-xxhdpi/blackboard.png b/res/drawable-xxhdpi/blackboard.png
new file mode 100644
index 0000000..0881d3b
--- /dev/null
+++ b/res/drawable-xxhdpi/blackboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/blur.png b/res/drawable-xxhdpi/blur.png
new file mode 100644
index 0000000..9cd27ee
--- /dev/null
+++ b/res/drawable-xxhdpi/blur.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_help.png b/res/drawable-xxhdpi/btn_tp_help.png
new file mode 100644
index 0000000..9573257
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_help.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_help_sel.png b/res/drawable-xxhdpi/btn_tp_help_sel.png
new file mode 100644
index 0000000..554774c
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_help_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_sel_bg.png b/res/drawable-xxhdpi/btn_tp_sel_bg.png
new file mode 100644
index 0000000..8d6eea0
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_sel_bg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_sel_bg_sel.png b/res/drawable-xxhdpi/btn_tp_sel_bg_sel.png
new file mode 100644
index 0000000..f0e53af
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_sel_bg_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_touchup.png b/res/drawable-xxhdpi/btn_tp_touchup.png
new file mode 100644
index 0000000..4113cb7
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_touchup.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_touchup_sel.png b/res/drawable-xxhdpi/btn_tp_touchup_sel.png
new file mode 100644
index 0000000..52acfba
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_touchup_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_undo.png b/res/drawable-xxhdpi/btn_tp_undo.png
new file mode 100644
index 0000000..448608d
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_undo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_undo_disabled.png b/res/drawable-xxhdpi/btn_tp_undo_disabled.png
new file mode 100644
index 0000000..71270ae
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_undo_disabled.png
Binary files differ
diff --git a/res/drawable-xxhdpi/btn_tp_undo_sel.png b/res/drawable-xxhdpi/btn_tp_undo_sel.png
new file mode 100644
index 0000000..25a2098
--- /dev/null
+++ b/res/drawable-xxhdpi/btn_tp_undo_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/bw.png b/res/drawable-xxhdpi/bw.png
new file mode 100644
index 0000000..a2accdd
--- /dev/null
+++ b/res/drawable-xxhdpi/bw.png
Binary files differ
diff --git a/res/drawable-xxhdpi/drawer_bg.png b/res/drawable-xxhdpi/drawer_bg.png
new file mode 100644
index 0000000..adc7e4a
--- /dev/null
+++ b/res/drawable-xxhdpi/drawer_bg.png
Binary files differ
diff --git a/res/drawable-xxhdpi/feather.png b/res/drawable-xxhdpi/feather.png
new file mode 100644
index 0000000..bb8069e
--- /dev/null
+++ b/res/drawable-xxhdpi/feather.png
Binary files differ
diff --git a/res/drawable-xxhdpi/filtershow_dualcam_focus.png b/res/drawable-xxhdpi/filtershow_dualcam_focus.png
new file mode 100644
index 0000000..57de383
--- /dev/null
+++ b/res/drawable-xxhdpi/filtershow_dualcam_focus.png
Binary files differ
diff --git a/res/drawable-xxhdpi/filtershow_dualcam_fusion.png b/res/drawable-xxhdpi/filtershow_dualcam_fusion.png
new file mode 100644
index 0000000..8533a90
--- /dev/null
+++ b/res/drawable-xxhdpi/filtershow_dualcam_fusion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/filtershow_dualcam_halo.png b/res/drawable-xxhdpi/filtershow_dualcam_halo.png
new file mode 100644
index 0000000..345c1f8
--- /dev/null
+++ b/res/drawable-xxhdpi/filtershow_dualcam_halo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/filtershow_dualcam_sketch.png b/res/drawable-xxhdpi/filtershow_dualcam_sketch.png
new file mode 100644
index 0000000..383dcff
--- /dev/null
+++ b/res/drawable-xxhdpi/filtershow_dualcam_sketch.png
Binary files differ
diff --git a/res/drawable-xxhdpi/focus.png b/res/drawable-xxhdpi/focus.png
new file mode 100644
index 0000000..8d58fd6
--- /dev/null
+++ b/res/drawable-xxhdpi/focus.png
Binary files differ
diff --git a/res/drawable-xxhdpi/fusion.png b/res/drawable-xxhdpi/fusion.png
new file mode 100644
index 0000000..1e88b9b
--- /dev/null
+++ b/res/drawable-xxhdpi/fusion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/halo.png b/res/drawable-xxhdpi/halo.png
new file mode 100644
index 0000000..99ed56f
--- /dev/null
+++ b/res/drawable-xxhdpi/halo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_large.png b/res/drawable-xxhdpi/ic_brush_size_large.png
new file mode 100644
index 0000000..6b91b53
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_large.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_large_sel.png b/res/drawable-xxhdpi/ic_brush_size_large_sel.png
new file mode 100644
index 0000000..9371f30
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_large_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_med.png b/res/drawable-xxhdpi/ic_brush_size_med.png
new file mode 100644
index 0000000..8a7e9e1
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_med.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_med_sel.png b/res/drawable-xxhdpi/ic_brush_size_med_sel.png
new file mode 100644
index 0000000..d02b0c0
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_med_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_sm.png b/res/drawable-xxhdpi/ic_brush_size_sm.png
new file mode 100644
index 0000000..5757c95
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_sm.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_brush_size_sm_sel.png b/res/drawable-xxhdpi/ic_brush_size_sm_sel.png
new file mode 100644
index 0000000..28829b2
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_brush_size_sm_sel.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_photoeditor_dualcam.png b/res/drawable-xxhdpi/ic_photoeditor_dualcam.png
new file mode 100644
index 0000000..0953e2c
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_photoeditor_dualcam.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_photoeditor_makeup_xx.png b/res/drawable-xxhdpi/ic_photoeditor_makeup_xx.png
new file mode 100644
index 0000000..3db1df2
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_photoeditor_makeup_xx.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_bokeh.png b/res/drawable-xxhdpi/ic_tp_bokeh.png
new file mode 100644
index 0000000..598e7d4
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_bokeh.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_fusion.png b/res/drawable-xxhdpi/ic_tp_fusion.png
new file mode 100644
index 0000000..59daba4
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_fusion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_halo.png b/res/drawable-xxhdpi/ic_tp_halo.png
new file mode 100644
index 0000000..2f60876
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_halo.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_motion_blur.png b/res/drawable-xxhdpi/ic_tp_motion_blur.png
new file mode 100644
index 0000000..2b88c9b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_motion_blur.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_normal.png b/res/drawable-xxhdpi/ic_tp_normal.png
new file mode 100644
index 0000000..2a153ff
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_normal.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tp_sketch.png b/res/drawable-xxhdpi/ic_tp_sketch.png
new file mode 100644
index 0000000..cbc7d7b
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tp_sketch.png
Binary files differ
diff --git a/res/drawable-xxhdpi/motion.png b/res/drawable-xxhdpi/motion.png
new file mode 100644
index 0000000..7eb4c2c
--- /dev/null
+++ b/res/drawable-xxhdpi/motion.png
Binary files differ
diff --git a/res/drawable-xxhdpi/multiselect.png b/res/drawable-xxhdpi/multiselect.png
new file mode 100644
index 0000000..6ec2985
--- /dev/null
+++ b/res/drawable-xxhdpi/multiselect.png
Binary files differ
diff --git a/res/drawable-xxhdpi/negative.png b/res/drawable-xxhdpi/negative.png
new file mode 100644
index 0000000..90a609f
--- /dev/null
+++ b/res/drawable-xxhdpi/negative.png
Binary files differ
diff --git a/res/drawable-xxhdpi/none.png b/res/drawable-xxhdpi/none.png
new file mode 100644
index 0000000..6e54e7d
--- /dev/null
+++ b/res/drawable-xxhdpi/none.png
Binary files differ
diff --git a/res/drawable-xxhdpi/play_detail.png b/res/drawable-xxhdpi/play_detail.png
new file mode 100644
index 0000000..01fc30f
--- /dev/null
+++ b/res/drawable-xxhdpi/play_detail.png
Binary files differ
diff --git a/res/drawable-xxhdpi/posterize.png b/res/drawable-xxhdpi/posterize.png
new file mode 100644
index 0000000..0bc95df
--- /dev/null
+++ b/res/drawable-xxhdpi/posterize.png
Binary files differ
diff --git a/res/drawable-xxhdpi/random.png b/res/drawable-xxhdpi/random.png
new file mode 100644
index 0000000..78140f7
--- /dev/null
+++ b/res/drawable-xxhdpi/random.png
Binary files differ
diff --git a/res/drawable-xxhdpi/rectangle.png b/res/drawable-xxhdpi/rectangle.png
new file mode 100644
index 0000000..ba45378
--- /dev/null
+++ b/res/drawable-xxhdpi/rectangle.png
Binary files differ
diff --git a/res/drawable-xxhdpi/round.png b/res/drawable-xxhdpi/round.png
new file mode 100644
index 0000000..3d9282f
--- /dev/null
+++ b/res/drawable-xxhdpi/round.png
Binary files differ
diff --git a/res/drawable-xxhdpi/sketch.png b/res/drawable-xxhdpi/sketch.png
new file mode 100644
index 0000000..be89c59
--- /dev/null
+++ b/res/drawable-xxhdpi/sketch.png
Binary files differ
diff --git a/res/drawable-xxhdpi/square.png b/res/drawable-xxhdpi/square.png
new file mode 100644
index 0000000..d339d8e
--- /dev/null
+++ b/res/drawable-xxhdpi/square.png
Binary files differ
diff --git a/res/drawable-xxhdpi/text_select_handle_left.png b/res/drawable-xxhdpi/text_select_handle_left.png
new file mode 100644
index 0000000..dbfa59c
--- /dev/null
+++ b/res/drawable-xxhdpi/text_select_handle_left.png
Binary files differ
diff --git a/res/drawable-xxhdpi/text_select_handle_right.png b/res/drawable-xxhdpi/text_select_handle_right.png
new file mode 100644
index 0000000..f161017
--- /dev/null
+++ b/res/drawable-xxhdpi/text_select_handle_right.png
Binary files differ
diff --git a/res/drawable-xxhdpi/three_d.png b/res/drawable-xxhdpi/three_d.png
new file mode 100644
index 0000000..ab58b45
--- /dev/null
+++ b/res/drawable-xxhdpi/three_d.png
Binary files differ
diff --git a/res/drawable-xxhdpi/trueportrait.png b/res/drawable-xxhdpi/trueportrait.png
new file mode 100644
index 0000000..3b46c80
--- /dev/null
+++ b/res/drawable-xxhdpi/trueportrait.png
Binary files differ
diff --git a/res/drawable-xxhdpi/trueportrait_disabled.png b/res/drawable-xxhdpi/trueportrait_disabled.png
new file mode 100644
index 0000000..93d4926
--- /dev/null
+++ b/res/drawable-xxhdpi/trueportrait_disabled.png
Binary files differ
diff --git a/res/drawable-xxhdpi/trueportrait_select.png b/res/drawable-xxhdpi/trueportrait_select.png
new file mode 100644
index 0000000..d5c3b5d
--- /dev/null
+++ b/res/drawable-xxhdpi/trueportrait_select.png
Binary files differ
diff --git a/res/drawable-xxhdpi/whiteboard.png b/res/drawable-xxhdpi/whiteboard.png
new file mode 100644
index 0000000..f584c3f
--- /dev/null
+++ b/res/drawable-xxhdpi/whiteboard.png
Binary files differ
diff --git a/res/drawable-xxhdpi/zoom.png b/res/drawable-xxhdpi/zoom.png
new file mode 100644
index 0000000..2c1dd02
--- /dev/null
+++ b/res/drawable-xxhdpi/zoom.png
Binary files differ
diff --git a/res/drawable/addspot.xml b/res/drawable/addspot.xml
new file mode 100644
index 0000000..5e3064e
--- /dev/null
+++ b/res/drawable/addspot.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M19.316,16.303v-4.351h-1.66v4.351h-4.264v1.707h4.264v4.328h1.66V18.01h4.27v-1.707H19.316zM7.814,1.638c-4.087,0 -7.4,3.313 -7.4,7.401c0,4.088 3.313,7.4 7.4,7.4s7.4,-3.313 7.4,-7.4C15.215,4.952 11.901,1.638 7.814,1.638zM7.729,15.008c-3.353,0 -6.07,-2.718 -6.07,-6.071s2.718,-6.071 6.07,-6.071c3.354,0 6.071,2.718 6.071,6.071S11.083,15.008 7.729,15.008zM7.729,4.513c-2.47,0 -4.472,2.002 -4.472,4.472s2.002,4.472 4.472,4.472s4.472,-2.002 4.472,-4.472S10.199,4.513 7.729,4.513z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/adjust.xml b/res/drawable/adjust.xml
new file mode 100644
index 0000000..ac0cff0
--- /dev/null
+++ b/res/drawable/adjust.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="12dp"
+        android:height="12dp"
+        android:viewportWidth="12.0"
+        android:viewportHeight="12.0">
+    <path
+        android:pathData="M5.984,6.016m-5.859,0a5.859,5.859 0,1 1,11.718 0a5.859,5.859 0,1 1,-11.718 0"
+        android:fillColor="#4f92e9"/>
+</vector>
diff --git a/res/drawable/albums.xml b/res/drawable/albums.xml
new file mode 100644
index 0000000..23630a5
--- /dev/null
+++ b/res/drawable/albums.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M17.999,2h-12c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C19.999,2.9 19.099,2 17.999,2zM5.999,4h5v8l-2.5,-1.5l-2.5,1.5V4zM5.999,19l3,-3.859l2.141,2.58l3,-3.861L17.999,19H5.999z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/arrow.xml b/res/drawable/arrow.xml
new file mode 100644
index 0000000..4f8d92c
--- /dev/null
+++ b/res/drawable/arrow.xml
@@ -0,0 +1,35 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="50.0"
+    android:viewportWidth="60.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFF"
+        android:pathData="M0,25.001l8.975,0l13.434,-14.917l0.18,0l13.433,14.917l8.977,0l-22.41,-25.001l-0.18,0z"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/arrow_down.xml b/res/drawable/arrow_down.xml
new file mode 100644
index 0000000..61afba0
--- /dev/null
+++ b/res/drawable/arrow_down.xml
@@ -0,0 +1,35 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="50.0"
+    android:viewportWidth="60.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFF"
+        android:pathData="M0,-0l8.975,0l13.434,14.917l0.18,0l13.433,-14.917l8.977,0l-22.41,25.001l-0.18,0z"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/back.xml b/res/drawable/back.xml
new file mode 100644
index 0000000..051e5b9
--- /dev/null
+++ b/res/drawable/back.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8l8,8l1.41,-1.41L7.83,13H20V11z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/beautify.xml b/res/drawable/beautify.xml
new file mode 100644
index 0000000..6962bc6
--- /dev/null
+++ b/res/drawable/beautify.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M26.305,8.769c-0.433,0.9 -0.486,2.1 -0.486,2.1s-0.175,-1.205 -0.619,-2.128c-0.395,-0.822 -1.93,-1.111 -1.93,-1.111s1.492,-0.138 1.879,-0.938c0.451,-0.939 0.623,-2.139 0.623,-2.139s0.107,1.136 0.571,2.103c0.366,0.758 1.854,0.98 1.854,0.98S26.714,7.919 26.305,8.769zM24.283,18.035c0,0 0.081,-1.424 -0.418,-3.219c-1.354,-4.873 -3.568,-6.139 -3.568,-6.139s2.77,0.869 4.727,5.355C26.087,16.468 24.283,18.035 24.283,18.035zM23.139,17.76c0,0 0.488,1.772 -0.889,4.784c-1.379,3.017 -4.73,4.065 -4.73,4.065s2.842,-1.843 4.154,-4.443C22.706,20.119 23.139,17.76 23.139,17.76zM14.925,13.241c-2.487,1.971 -3.536,4.087 -3.536,7.08c0,3.931 5.176,7.127 5.176,7.127s-6.6,-2.607 -6.6,-7.426c0,-2.614 0.661,-5.133 1.835,-7.062c-0.72,0.654 -1.383,1.438 -1.868,2.416c-1.315,2.659 -0.804,6.175 -0.804,6.175c-2.54,-2.602 -3.533,-6.776 -2.229,-10.197c1.196,-3.136 3.49,-5.457 5.399,-6.058c3.968,-1.25 4.969,0.568 4.969,0.568s0.031,0.09 0.07,0.244c0.045,-0.37 -0.014,-0.573 -0.014,-0.573S21.336,8.16 14.925,13.241zM5.774,23.086c-0.294,0.622 -0.372,1.321 -0.372,1.321s-0.078,-0.701 -0.381,-1.34c-0.269,-0.566 -1.251,-0.704 -1.251,-0.704s0.954,-0.158 1.216,-0.711c0.307,-0.649 0.424,-1.481 0.424,-1.481s0.073,0.789 0.39,1.456C6.049,22.152 7,22.351 7,22.351S6.053,22.501 5.774,23.086zM24.859,22.814c0.478,-1.109 0.659,-2.631 0.659,-2.631s0.112,1.447 0.605,2.59c0.384,0.895 2.104,0.973 2.104,0.973s-1.716,0.152 -2.145,1.155c-0.459,1.063 -0.622,2.521 -0.622,2.521s-0.08,-1.464 -0.549,-2.553c-0.418,-0.972 -2.063,-1.146 -2.063,-1.146l-0.028,-0.004C22.822,23.72 24.451,23.762 24.859,22.814z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/beautify_background.xml b/res/drawable/beautify_background.xml
new file mode 100644
index 0000000..26f13a6
--- /dev/null
+++ b/res/drawable/beautify_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/beautify" android:state_selected="false"></item>
+    <item android:drawable="@drawable/beautify_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/beautify_select.xml b/res/drawable/beautify_select.xml
new file mode 100644
index 0000000..68cff58
--- /dev/null
+++ b/res/drawable/beautify_select.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M26.305,8.769c-0.433,0.9 -0.486,2.1 -0.486,2.1s-0.175,-1.205 -0.619,-2.128c-0.395,-0.822 -1.93,-1.111 -1.93,-1.111s1.492,-0.138 1.879,-0.938c0.451,-0.939 0.623,-2.139 0.623,-2.139s0.107,1.136 0.571,2.103c0.366,0.758 1.854,0.98 1.854,0.98S26.714,7.919 26.305,8.769zM24.283,18.035c0,0 0.081,-1.424 -0.418,-3.219c-1.354,-4.873 -3.568,-6.139 -3.568,-6.139s2.77,0.869 4.727,5.355C26.087,16.468 24.283,18.035 24.283,18.035zM23.139,17.76c0,0 0.488,1.772 -0.889,4.784c-1.379,3.017 -4.73,4.065 -4.73,4.065s2.842,-1.843 4.154,-4.443C22.706,20.119 23.139,17.76 23.139,17.76zM14.925,13.241c-2.487,1.971 -3.536,4.087 -3.536,7.08c0,3.931 5.176,7.127 5.176,7.127s-6.6,-2.607 -6.6,-7.426c0,-2.614 0.661,-5.133 1.835,-7.062c-0.72,0.654 -1.383,1.438 -1.868,2.416c-1.315,2.659 -0.804,6.175 -0.804,6.175c-2.54,-2.602 -3.533,-6.776 -2.229,-10.197c1.196,-3.136 3.49,-5.457 5.399,-6.058c3.968,-1.25 4.969,0.568 4.969,0.568s0.031,0.09 0.07,0.244c0.045,-0.37 -0.014,-0.573 -0.014,-0.573S21.336,8.16 14.925,13.241zM5.774,23.086c-0.294,0.622 -0.372,1.321 -0.372,1.321s-0.078,-0.701 -0.381,-1.34c-0.269,-0.566 -1.251,-0.704 -1.251,-0.704s0.954,-0.158 1.216,-0.711c0.307,-0.649 0.424,-1.481 0.424,-1.481s0.073,0.789 0.39,1.456C6.049,22.152 7,22.351 7,22.351S6.053,22.501 5.774,23.086zM24.859,22.814c0.478,-1.109 0.659,-2.631 0.659,-2.631s0.112,1.447 0.605,2.59c0.384,0.895 2.104,0.973 2.104,0.973s-1.716,0.152 -2.145,1.155c-0.459,1.063 -0.622,2.521 -0.622,2.521s-0.08,-1.464 -0.549,-2.553c-0.418,-0.972 -2.063,-1.146 -2.063,-1.146l-0.028,-0.004C22.822,23.72 24.451,23.762 24.859,22.814z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/bg_vidcontrol.xml b/res/drawable/bg_vidcontrol.xml
new file mode 100644
index 0000000..9ce9f6a
--- /dev/null
+++ b/res/drawable/bg_vidcontrol.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0">
+    <path
+        android:fillColor="@color/black"
+        android:fillAlpha="0.5"
+        android:pathData="M24,24m-24,0a24,24 0,1 1,48 0a24,24 0,1 1,-48 0" />
+</vector>
diff --git a/res/drawable/camera.xml b/res/drawable/camera.xml
new file mode 100644
index 0000000..6249f89
--- /dev/null
+++ b/res/drawable/camera.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 12 9.799 C 13.7673111995 9.799 15.2 11.2316888005 15.2 12.999 C 15.2 14.7663111995 13.7673111995 16.199 12 16.199 C 10.2326888005 16.199 8.8 14.7663111995 8.8 12.999 C 8.8 11.2316888005 10.2326888005 9.799 12 9.799 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M9,3L7.17,5H4c-1.1,0-2,0.9-2,2v12c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V7c0-1.1-0.9-2-2-2h-3.17L15,3H9z
+M12,18c-2.76,0-5-2.24-5-5c0-2.76,2.24-5,5-5s5,2.24,5,5C17,15.76,14.76,18,12,18z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/cancel.xml b/res/drawable/cancel.xml
new file mode 100644
index 0000000..335e609
--- /dev/null
+++ b/res/drawable/cancel.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M19.205,6.41L17.795,5l-5.59,5.59L6.615,5l-1.41,1.41l5.59,5.59l-5.59,5.59L6.615,19l5.59,-5.59l5.59,5.59l1.41,-1.41L13.615,12L19.205,6.41z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/cancel2.xml b/res/drawable/cancel2.xml
new file mode 100644
index 0000000..82eaec1
--- /dev/null
+++ b/res/drawable/cancel2.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M19.205,6.41L17.795,5l-5.59,5.59L6.615,5l-1.41,1.41l5.59,5.59l-5.59,5.59L6.615,19l5.59,-5.59l5.59,5.59l1.41,-1.41L13.615,12L19.205,6.41z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/color.xml b/res/drawable/color.xml
new file mode 100644
index 0000000..d2dc37e
--- /dev/null
+++ b/res/drawable/color.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M16,4.951C9.898,4.951 4.951,9.898 4.951,16c0,6.102 4.947,11.049 11.049,11.049c1.02,0 1.842,-0.822 1.842,-1.842c0,-0.479 -0.178,-0.908 -0.479,-1.232c-0.289,-0.326 -0.461,-0.75 -0.461,-1.223c0,-1.02 0.822,-1.842 1.842,-1.842h2.166c3.389,0 6.139,-2.75 6.139,-6.138C27.049,9.347 22.102,4.951 16,4.951zM9.248,16c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.841 1.842,-1.841s1.842,0.822 1.842,1.841C11.09,15.178 10.268,16 9.248,16zM12.932,11.09c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.842 1.842,-1.842c1.018,0 1.84,0.823 1.84,1.842C14.771,10.268 13.949,11.09 12.932,11.09zM19.068,11.09c-1.021,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.821,-1.842 1.842,-1.842c1.02,0 1.842,0.823 1.842,1.842C20.91,10.268 20.088,11.09 19.068,11.09zM22.752,16c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.841 1.842,-1.841s1.842,0.822 1.842,1.841C24.594,15.178 23.771,16 22.752,16z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/color_background.xml b/res/drawable/color_background.xml
new file mode 100644
index 0000000..1d4c1f6
--- /dev/null
+++ b/res/drawable/color_background.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/color" android:state_selected="false"></item>
+    <item android:drawable="@drawable/color_select" android:state_selected="true"></item>
+
+</selector>
\ No newline at end of file
diff --git a/res/drawable/color_select.xml b/res/drawable/color_select.xml
new file mode 100644
index 0000000..79d1070
--- /dev/null
+++ b/res/drawable/color_select.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M16,4.951C9.898,4.951 4.951,9.898 4.951,16c0,6.102 4.947,11.049 11.049,11.049c1.02,0 1.842,-0.822 1.842,-1.842c0,-0.479 -0.178,-0.908 -0.479,-1.232c-0.289,-0.326 -0.461,-0.75 -0.461,-1.223c0,-1.02 0.822,-1.842 1.842,-1.842h2.166c3.389,0 6.139,-2.75 6.139,-6.138C27.049,9.347 22.102,4.951 16,4.951zM9.248,16c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.841 1.842,-1.841s1.842,0.822 1.842,1.841C11.09,15.178 10.268,16 9.248,16zM12.932,11.09c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.842 1.842,-1.842c1.018,0 1.84,0.823 1.84,1.842C14.771,10.268 13.949,11.09 12.932,11.09zM19.068,11.09c-1.021,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.821,-1.842 1.842,-1.842c1.02,0 1.842,0.823 1.842,1.842C20.91,10.268 20.088,11.09 19.068,11.09zM22.752,16c-1.02,0 -1.842,-0.822 -1.842,-1.842c0,-1.019 0.822,-1.841 1.842,-1.841s1.842,0.822 1.842,1.841C24.594,15.178 23.771,16 22.752,16z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/comparison.xml b/res/drawable/comparison.xml
new file mode 100644
index 0000000..36c5331
--- /dev/null
+++ b/res/drawable/comparison.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@drawable/comparison_after" />
+    <item android:drawable="@drawable/comparison_before" />
+</selector>
+
diff --git a/res/drawable/comparison_after.xml b/res/drawable/comparison_after.xml
new file mode 100644
index 0000000..262aa41
--- /dev/null
+++ b/res/drawable/comparison_after.xml
@@ -0,0 +1,42 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="36dp"
+        android:height="36dp"
+        android:viewportWidth="36.0"
+        android:viewportHeight="36.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M18,1c9.389,0 17,7.611 17,17c0,9.388 -7.611,17 -17,17C8.612,35 1,27.388 1,18C1,8.611 8.612,1 18,1z"
+        android:fillAlpha="0.26"/>
+    <path
+        android:pathData="M9.258,16h1.333v-1.333H9.258V16zM9.258,18.667h1.333v-1.334H9.258V18.667zM9.258,21.333h1.333V20H9.258V21.333zM10.591,23.999v-1.333H9.258C9.258,23.402 9.854,23.999 10.591,23.999zM9.258,13.334h1.333v-1.333C9.854,12.001 9.258,12.598 9.258,13.334zM17.334,25.332h1.333V10.667h-1.333V25.332zM14.667,23.999H16v-1.333h-1.333V23.999zM25.408,12.001h-5.37v1.333h5.37v9.332h-5.37v1.333h5.37c0.737,0 1.334,-0.597 1.334,-1.333v-9.332C26.742,12.598 26.146,12.001 25.408,12.001zM15.97,12.001h-1.333v1.333h1.333V12.001zM11.955,13.334h1.334v-1.333h-1.334V13.334zM11.955,23.999h1.334v-1.333h-1.334V23.999z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/comparison_before.xml b/res/drawable/comparison_before.xml
new file mode 100644
index 0000000..5066cd9
--- /dev/null
+++ b/res/drawable/comparison_before.xml
@@ -0,0 +1,42 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="36dp"
+        android:height="36dp"
+        android:viewportWidth="36.0"
+        android:viewportHeight="36.0">
+    <path
+        android:pathData="M18,1c9.389,0 17,7.611 17,17c0,9.388 -7.611,17 -17,17C8.612,35 1,27.388 1,18C1,8.611 8.612,1 18,1z"
+        android:fillAlpha="0.50"
+        android:fillColor="@color/black"/>
+    <path
+        android:pathData="M9.258,16h1.333v-1.333H9.258V16zM10.591,23.999v-1.333H9.258C9.258,23.402 9.854,23.999 10.591,23.999zM9.258,13.334h1.333v-1.333C9.854,12.001 9.258,12.598 9.258,13.334zM9.258,21.333h1.333V20H9.258V21.333zM9.258,18.667h1.333v-1.334H9.258V18.667zM14.667,23.999H16v-1.333h-1.333V23.999zM25.408,12.001h-5.37v1.333h5.37v9.332h-5.37v1.333h5.37c0.737,0 1.334,-0.597 1.334,-1.333v-9.332C26.742,12.598 26.146,12.001 25.408,12.001zM17.334,25.332h1.333V10.667h-1.333V25.332zM15.97,12.001h-1.333v1.333h1.333V12.001zM11.955,13.334h1.334v-1.333h-1.334V13.334zM11.955,23.999h1.334v-1.333h-1.334V23.999z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/crop.xml b/res/drawable/crop.xml
new file mode 100644
index 0000000..25ff649
--- /dev/null
+++ b/res/drawable/crop.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M20.911,19.324h2.28v-8.26c0,-1.127 -0.945,-2.438 -2.073,-2.438h-8.262v2.312h8.055V19.324zM11.117,21.008v-16.4H8.809v4.019h-4.02l-0.031,2.315l4.051,-0.004V21.27c0,1.127 0.914,2.041 2.041,2.041h10.03v4.082h2.312v-4.082h4.052v-2.303H11.117z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/crop_1_1.xml b/res/drawable/crop_1_1.xml
new file mode 100644
index 0000000..332eff7
--- /dev/null
+++ b/res/drawable/crop_1_1.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M3,3L3,87L87,87L87,3L3,3ZM78.99,78.99L11.01,78.99L11.01,11.01L78.99,11.01L78.99,78.99Z"/>
+</vector>
diff --git a/res/drawable/crop_1_1_select.xml b/res/drawable/crop_1_1_select.xml
new file mode 100644
index 0000000..8928707
--- /dev/null
+++ b/res/drawable/crop_1_1_select.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF4F92E9" android:pathData="M3,3L3,87L87,87L87,3L3,3ZM78.99,78.99L11.01,78.99L11.01,11.01L78.99,11.01L78.99,78.99Z"/>
+</vector>
diff --git a/res/drawable/crop_background.xml b/res/drawable/crop_background.xml
new file mode 100644
index 0000000..079b077
--- /dev/null
+++ b/res/drawable/crop_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/crop" android:state_selected="false"></item>
+    <item android:drawable="@drawable/crop_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/crop_crop.xml b/res/drawable/crop_crop.xml
new file mode 100644
index 0000000..0272da2
--- /dev/null
+++ b/res/drawable/crop_crop.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M15,67C15,71.42 18.58,75 23,75L23,75L67,75L67,87L75,87L75,75L87,75L87,67L23,67L23,3L15,3L15,15L3,15L3,23L15,23L15,67ZM67,59L75,59L75,23C75,18.58 71.42,15 67,15L31,15L31,23L67,23L67,59Z"/>
+</vector>
diff --git a/res/drawable/crop_free.xml b/res/drawable/crop_free.xml
new file mode 100644
index 0000000..eac62fb
--- /dev/null
+++ b/res/drawable/crop_free.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M11,62L3,62L3,87L28,87L28,79L11,79L11,62ZM79,79L62,79L62,87L87,87L87,62L79,62L79,79ZM3,28L11,28L11,11L28,11L28,3L3,3L3,28ZM62,3L62,11L79,11L79,28L87,28L87,3L62,3Z"/>
+</vector>
diff --git a/res/drawable/crop_free_background.xml b/res/drawable/crop_free_background.xml
new file mode 100644
index 0000000..4404d4e
--- /dev/null
+++ b/res/drawable/crop_free_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/crop_free" android:state_selected="false"></item>
+    <item android:drawable="@drawable/crop_free_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/crop_free_select.xml b/res/drawable/crop_free_select.xml
new file mode 100644
index 0000000..f246997
--- /dev/null
+++ b/res/drawable/crop_free_select.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF4F92E9" android:pathData="M11,62L3,62L3,87L28,87L28,79L11,79L11,62ZM79,79L62,79L62,87L87,87L87,62L79,62L79,79ZM3,28L11,28L11,11L28,11L28,3L3,3L3,28ZM62,3L62,11L79,11L79,28L87,28L87,3L62,3Z"/>
+</vector>
diff --git a/res/drawable/crop_one_background.xml b/res/drawable/crop_one_background.xml
new file mode 100644
index 0000000..aa035ed
--- /dev/null
+++ b/res/drawable/crop_one_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/crop_1_1" android:state_selected="false"></item>
+    <item android:drawable="@drawable/crop_1_1_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/crop_original.xml b/res/drawable/crop_original.xml
new file mode 100644
index 0000000..91eef6c
--- /dev/null
+++ b/res/drawable/crop_original.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M9,1L9,89L81,89L81,1L9,1ZM17,46L44,46L44,81L17,81L17,46ZM73,81L48,81L48,42L17,42L17,9L73,9L73,81Z"/>
+</vector>
diff --git a/res/drawable/crop_original_background.xml b/res/drawable/crop_original_background.xml
new file mode 100644
index 0000000..eafe861
--- /dev/null
+++ b/res/drawable/crop_original_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/crop_original" android:state_selected="false"></item>
+    <item android:drawable="@drawable/crop_original_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/crop_original_select.xml b/res/drawable/crop_original_select.xml
new file mode 100644
index 0000000..3bb0f76
--- /dev/null
+++ b/res/drawable/crop_original_select.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF4F92E9" android:pathData="M9,1L9,89L81,89L81,1L9,1ZM17,46L44,46L44,81L17,81L17,46ZM73,81L48,81L48,42L17,42L17,9L73,9L73,81Z"/>
+</vector>
diff --git a/res/drawable/crop_rotate.xml b/res/drawable/crop_rotate.xml
new file mode 100644
index 0000000..8caf459
--- /dev/null
+++ b/res/drawable/crop_rotate.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="90.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M45,5C32.42,5 21.21,10.81 13.88,19.88L5,11L5.01,33.99L6.55,33.99C6.55,33.99 6.55,34 6.54,34L14.94,34C14.94,34 14.94,33.99 14.95,33.99L27.99,33.99L19.57,25.57C25.42,17.93 34.63,13 45,13C62.67,13 77,27.33 77,45C77,62.67 62.67,77 45,77C27.33,77 13,62.67 13,45L5,45C5,67.09 22.91,85 45,85C67.09,85 85,67.09 85,45C85,22.91 67.09,5 45,5Z"/>
+</vector>
diff --git a/res/drawable/crop_select.xml b/res/drawable/crop_select.xml
new file mode 100644
index 0000000..f2a8269
--- /dev/null
+++ b/res/drawable/crop_select.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M20.911,19.324h2.28v-8.26c0,-1.127 -0.945,-2.438 -2.073,-2.438h-8.262v2.312h8.055V19.324zM11.117,21.008v-16.4H8.809v4.019h-4.02l-0.031,2.315l4.051,-0.004V21.27c0,1.127 0.914,2.041 2.041,2.041h10.03v4.082h2.312v-4.082h4.052v-2.303H11.117z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/crop_straighten.xml b/res/drawable/crop_straighten.xml
new file mode 100644
index 0000000..9fda1f4
--- /dev/null
+++ b/res/drawable/crop_straighten.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="90.0"
+    android:viewportWidth="89.844" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFFFF" android:pathData="M87.85,22.54L73.87,22.54L73.87,29.53L82.86,29.53L82.86,75.44L48.91,75.44L48.91,82.43L87.85,82.43C88.95,82.43 89.84,81.53 89.84,80.43L89.84,24.54C89.84,23.44 88.95,22.54 87.85,22.54ZM74.82,64.32L65.09,9.23C64.9,8.15 63.86,7.42 62.77,7.61L1.66,18.37C0.57,18.56 -0.16,19.6 0.03,20.68L9.77,75.77C9.96,76.86 11,77.59 12.09,77.39L73.2,66.64C74.29,66.45 75.01,65.41 74.82,64.32ZM44.55,36.57L31.7,61L21.53,51.79L14.88,64.43L7.8,24.39L59.06,15.37L66.28,56.22L44.55,36.57Z"/>
+</vector>
diff --git a/res/drawable/delete.xml b/res/drawable/delete.xml
new file mode 100644
index 0000000..1285cb9
--- /dev/null
+++ b/res/drawable/delete.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M5.999,19.001c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2v-12h-12V19.001zM18.999,4.001h-3.5l-1,-1h-5l-1,1h-3.5v2h14V4.001z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/done.xml b/res/drawable/done.xml
new file mode 100644
index 0000000..439357c
--- /dev/null
+++ b/res/drawable/done.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M8.795,15.875l-4.17,-4.17l-1.42,1.41l5.59,5.59l12,-12l-1.41,-1.41L8.795,15.875z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/done2.xml b/res/drawable/done2.xml
new file mode 100644
index 0000000..76d5f56
--- /dev/null
+++ b/res/drawable/done2.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M8.795,15.875l-4.17,-4.17l-1.42,1.41l5.59,5.59l12,-12l-1.41,-1.41L8.795,15.875z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/drawer.xml b/res/drawable/drawer.xml
new file mode 100644
index 0000000..e0a8061
--- /dev/null
+++ b/res/drawable/drawer.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M2.989,18h18.022v-2H2.989V18zM2.989,13h18.022v-2H2.989V13zM2.989,6v2h18.022V6H2.989z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/drawer_item_selected_bg.xml b/res/drawable/drawer_item_selected_bg.xml
new file mode 100644
index 0000000..81d6ce8
--- /dev/null
+++ b/res/drawable/drawer_item_selected_bg.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+    <solid android:color="#D8D8D8" >
+    </solid>
+
+</shape>
\ No newline at end of file
diff --git a/res/drawable/dropdown_ic_arrow_normal_holo_dark.xml b/res/drawable/dropdown_ic_arrow_normal_holo_dark.xml
new file mode 100644
index 0000000..49788bf
--- /dev/null
+++ b/res/drawable/dropdown_ic_arrow_normal_holo_dark.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0">
+    <path
+        android:fillAlpha="0.54"
+        android:fillColor="@color/black"
+        android:pathData="M0,5h24l-12,14L0,5z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/dualcamera.xml b/res/drawable/dualcamera.xml
new file mode 100644
index 0000000..7bfdc46
--- /dev/null
+++ b/res/drawable/dualcamera.xml
@@ -0,0 +1,21 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M19.794,10.447H12.36c-1.152,0 -2.165,0.887 -2.165,2.04v7.912c0,1.153 1.012,2.086 2.165,2.086h7.434c1.154,0 2.011,-0.933 2.011,-2.086v-7.912C21.805,11.334 20.948,10.447 19.794,10.447zM19.865,20.57h-7.692v-8.175h7.692V20.57z"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M21,7h4v5h2V7.713C27,6.341 26.156,5 24.783,5H21V7z"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M7,12V7h4V5H7.399C6.027,5 5,6.341 5,7.713V12H7z"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M11,26H7v-5H5v4.098C5,26.471 6.027,28 7.399,28H11V26z"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M25,21v5h-4v2h3.783C26.156,28 27,26.471 27,25.098V21H25z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/dualcamera_background.xml b/res/drawable/dualcamera_background.xml
new file mode 100644
index 0000000..08e2147
--- /dev/null
+++ b/res/drawable/dualcamera_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/dualcamera" android:state_selected="false"></item>
+    <item android:drawable="@drawable/dualcamera_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/dualcamera_select.xml b/res/drawable/dualcamera_select.xml
new file mode 100644
index 0000000..9835120
--- /dev/null
+++ b/res/drawable/dualcamera_select.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M19.794,10.447H12.36c-1.152,0 -2.165,0.887 -2.165,2.04v7.912c0,1.153 1.012,2.086 2.165,2.086h7.434c1.154,0 2.011,-0.933 2.011,-2.086v-7.912C21.805,11.334 20.948,10.447 19.794,10.447zM19.865,20.57h-7.692v-8.175h7.692V20.57z"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M21,7h4v5h2V7.713C27,6.341 26.156,5 24.783,5H21V7z"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M7,12V7h4V5H7.399C6.027,5 5,6.341 5,7.713V12H7z"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M11,26H7v-5H5v4.098C5,26.471 6.027,28 7.399,28H11V26z"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M25,21v5h-4v2h3.783C26.156,28 27,26.471 27,25.098V21H25z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/edit.xml b/res/drawable/edit.xml
new file mode 100644
index 0000000..b28d23e
--- /dev/null
+++ b/res/drawable/edit.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M2.999,17.252v3.75h3.75l11.061,-11.06l-3.75,-3.75L2.999,17.252zM20.708,7.042c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.021,-0.39 -1.41,0l-1.83,1.83l3.75,3.75L20.708,7.042z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/exposure.xml b/res/drawable/exposure.xml
new file mode 100644
index 0000000..ad0a64f
--- /dev/null
+++ b/res/drawable/exposure.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M19.514,21.201v2.357h1.644l0.045,-2.357h2.313v-1.688h-2.357V17.2h-1.643v2.313h-2.357v1.688H19.514zM24.85,4.793H7.061c-1.228,0 -2.223,0.995 -2.223,2.224v17.788c0,1.229 0.995,2.402 2.223,2.402H24.85c1.229,0 2.313,-1.174 2.313,-2.402V7.017C27.161,5.789 26.077,4.793 24.85,4.793zM8.173,8.173h6.671v2H8.173V8.173zM25.161,25.162h-18.1l18.1,-18.541V25.162z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/exposure_background.xml b/res/drawable/exposure_background.xml
new file mode 100644
index 0000000..c892e09
--- /dev/null
+++ b/res/drawable/exposure_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/exposure" android:state_selected="false"></item>
+    <item android:drawable="@drawable/exposure_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/exposure_select.xml b/res/drawable/exposure_select.xml
new file mode 100644
index 0000000..7386e4c
--- /dev/null
+++ b/res/drawable/exposure_select.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M19.514,21.201v2.357h1.644l0.045,-2.357h2.313v-1.688h-2.357V17.2h-1.643v2.313h-2.357v1.688H19.514zM24.85,4.793H7.061c-1.228,0 -2.223,0.995 -2.223,2.224v17.788c0,1.229 0.995,2.402 2.223,2.402H24.85c1.229,0 2.313,-1.174 2.313,-2.402V7.017C27.161,5.789 26.077,4.793 24.85,4.793zM8.173,8.173h6.671v2H8.173V8.173zM25.161,25.162h-18.1l18.1,-18.541V25.162z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/filtershow_add_new.png b/res/drawable/filtershow_add_new.png
new file mode 100644
index 0000000..9fe060e
--- /dev/null
+++ b/res/drawable/filtershow_add_new.png
Binary files differ
diff --git a/res/drawable/filtershow_color_picker_circle.xml b/res/drawable/filtershow_color_picker_circle.xml
index 433df48..1457a68 100644
--- a/res/drawable/filtershow_color_picker_circle.xml
+++ b/res/drawable/filtershow_color_picker_circle.xml
@@ -21,6 +21,6 @@
         android:radius="0dp" />
     <solid android:color="@color/red"/>
     <stroke android:width="0dp"
-            android:color="#ff000000"/>
+            android:color="@color/black"/>
 </shape>
 
diff --git a/res/drawable/filtershow_menu_marker_rtl.xml b/res/drawable/filtershow_menu_marker_rtl.xml
index 1515004..a564985 100644
--- a/res/drawable/filtershow_menu_marker_rtl.xml
+++ b/res/drawable/filtershow_menu_marker_rtl.xml
@@ -1,4 +1,4 @@
 <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
-        android:src="@drawable/filtershow_menu_marker"
+        android:src="@drawable/spinner_triangle"
         android:autoMirrored="true">
 </bitmap>
\ No newline at end of file
diff --git a/res/drawable/filtershow_slider.xml b/res/drawable/filtershow_slider.xml
index 23457a6..80805dc 100644
--- a/res/drawable/filtershow_slider.xml
+++ b/res/drawable/filtershow_slider.xml
@@ -16,13 +16,13 @@
 -->
 <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@android:id/background"
-          android:drawable="@drawable/filtershow_scrubber_track" />
+          android:drawable="@drawable/sliderbg" />
     <item android:id="@android:id/secondaryProgress">
         <scale android:scaleWidth="100%"
-               android:drawable="@drawable/filtershow_scrubber_secondary" />
+               android:drawable="@drawable/sliderprogress" />
     </item>
     <item android:id="@android:id/progress">
         <scale android:scaleWidth="100%"
-               android:drawable="@drawable/filtershow_scrubber_primary" />
+               android:drawable="@drawable/sliderprogress" />
     </item>
 </layer-list>
\ No newline at end of file
diff --git a/res/drawable/filtershow_state_button_background b/res/drawable/filtershow_state_button_background
deleted file mode 100644
index e69de29..0000000
--- a/res/drawable/filtershow_state_button_background
+++ /dev/null
diff --git a/res/drawable/frames.xml b/res/drawable/frames.xml
new file mode 100644
index 0000000..f668e4d
--- /dev/null
+++ b/res/drawable/frames.xml
@@ -0,0 +1,44 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M24.934,8.228h-4.467L16,3.761l-4.468,4.467H7.065c-1.234,0 -2.233,1 -2.233,2.233v15.441c0,1.232 0.999,2.338 2.233,2.338h17.869c1.233,0 2.233,-1.104 2.233,-2.338V10.461C27.168,9.228 26.168,8.228 24.934,8.228zM25.178,26.25H6.822V10.252h5.285l3.932,-3.699l3.886,3.699h5.253V26.25z"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M23.143,12.216"
+        android:fillColor="@color/white"/>
+    <path
+        android:pathData="M8.923,12.216h14.153v11.966h-14.153z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/frames_background.xml b/res/drawable/frames_background.xml
new file mode 100644
index 0000000..0a572b9
--- /dev/null
+++ b/res/drawable/frames_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/frames" android:state_selected="false"></item>
+    <item android:drawable="@drawable/frames_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/frames_select.xml b/res/drawable/frames_select.xml
new file mode 100644
index 0000000..6fa77e7
--- /dev/null
+++ b/res/drawable/frames_select.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32dp"
+        android:height="32dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <path
+        android:pathData="M24.934,8.228h-4.467L16,3.761l-4.468,4.467H7.065c-1.234,0 -2.233,1 -2.233,2.233v15.441c0,1.232 0.999,2.338 2.233,2.338h17.869c1.233,0 2.233,-1.104 2.233,-2.338V10.461C27.168,9.228 26.168,8.228 24.934,8.228zM25.178,26.25H6.822V10.252h5.285l3.932,-3.699l3.886,3.699h5.253V26.25z"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M23.143,12.216"
+        android:fillColor="#FF4F92E9"/>
+    <path
+        android:pathData="M8.923,12.216h14.153v11.966h-14.153z"
+        android:fillColor="#FF4F92E9"/>
+</vector>
diff --git a/res/drawable/hazebuster.xml b/res/drawable/hazebuster.xml
new file mode 100644
index 0000000..0b157ac
--- /dev/null
+++ b/res/drawable/hazebuster.xml
@@ -0,0 +1,62 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M29,20.9c-0.9-0.5-2.1-0.5-3.1,0l-0.4,0.2c-0.7,0.4-1.7,0.4-2.3-0.1c-0.2-0.1-0.5-0.3-0.7-0.3
+c-0.2,0.3-0.5,0.5-0.8,0.7c0.4,0,0.8,0.1,1.1,0.3c0.9,0.6,2.3,0.7,3.2,0.1l0.4-0.2c0.7-0.4,1.6-0.4,2.2,0c0.2,0.1,0.5,0,0.6-0.2
+C29.3,21.3,29.2,21,29,20.9z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M29,16.2c-0.9-0.5-2.1-0.5-3.1,0l-0.4,0.2c-0.4,0.2-0.9,0.3-1.4,0.3c0,0,0,0,0,0.1c0,0.3,0,0.5-0.1,0.8
+c0.6,0.1,1.3-0.1,1.9-0.4l0.4-0.2c0.7-0.4,1.6-0.4,2.2,0c0.2,0.1,0.5,0,0.6-0.2C29.3,16.6,29.2,16.3,29,16.2z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M29,23.2c-0.9-0.5-2.1-0.5-3.1,0l-0.4,0.2c-0.7,0.4-1.7,0.4-2.3-0.1c-0.9-0.6-2.2-0.7-3.2-0.1l-0.3,0.2
+c-0.7,0.4-1.7,0.4-2.3-0.1c-0.9-0.6-2.2-0.7-3.2-0.1c-0.2,0.1-0.3,0.4-0.2,0.6c0.1,0.2,0.4,0.3,0.6,0.2c0.7-0.4,1.7-0.4,2.3,0.1
+c0.5,0.3,1.1,0.5,1.7,0.5c0.5,0,1.1-0.1,1.5-0.4l0.3-0.2c0.7-0.4,1.7-0.4,2.3,0.1c0.9,0.6,2.3,0.7,3.2,0.1l0.4-0.2
+c0.7-0.4,1.6-0.4,2.2,0c0.2,0.1,0.5,0,0.6-0.2C29.3,23.6,29.2,23.4,29,23.2z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M29,18.5c-0.9-0.5-2.1-0.5-3.1,0l-0.4,0.2c-0.5,0.3-1.2,0.4-1.8,0.2c-0.1,0.3-0.2,0.5-0.4,0.8
+c0.9,0.3,1.9,0.3,2.7-0.2l0.4-0.2c0.7-0.4,1.6-0.4,2.2,0c0.2,0.1,0.5,0,0.6-0.2C29.3,18.9,29.2,18.7,29,18.5z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M17.1,22.3c-1.1,0-2.2-0.2-3.2-0.7c-1.1,0.5-2.3,0.7-3.5,0.7c-4.2,0-7.7-2.9-7.7-6.5c0-2.6,1.8-5,4.6-6
+c0.9-1.9,3.2-3.2,5.6-3.2c3.2,0,5.9,2.1,6.1,4.8c2.7,0.7,4.6,2.9,4.6,5.3C23.6,19.8,20.7,22.3,17.1,22.3z
+M13.9,19.7l0.4,0.2
+c0.8,0.5,1.8,0.7,2.8,0.7c2.7,0,4.8-1.7,4.8-3.9c0-1.8-1.6-3.4-3.8-3.8l-0.8-0.1l0.1-0.8c0-0.1,0-0.1,0-0.2c0-1.9-2-3.5-4.4-3.5
+c-1.9,0-3.7,1-4.2,2.5l-0.1,0.4l-0.4,0.1c-2.3,0.7-3.8,2.5-3.8,4.5c0,2.7,2.7,4.8,6,4.8c1.1,0,2.2-0.3,3.1-0.7L13.9,19.7z" />
+</vector>
diff --git a/res/drawable/ic_album.xml b/res/drawable/ic_album.xml
new file mode 100644
index 0000000..3f0cfa2
--- /dev/null
+++ b/res/drawable/ic_album.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/tab_icon_2"
+        android:pathData="M17.999,2h-12c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C19.999,2.9 19.099,2 17.999,2zM5.999,4h5v8l-2.5,-1.5l-2.5,1.5V4zM5.999,19l3,-3.859l2.141,2.58l3,-3.861L17.999,19H5.999z"/>
+</vector>
diff --git a/res/drawable/ic_controller_brightness.xml b/res/drawable/ic_controller_brightness.xml
new file mode 100644
index 0000000..8c912fc
--- /dev/null
+++ b/res/drawable/ic_controller_brightness.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M87.94,39.94L87.94,20.06L68.06,20.06L54,6 39.94,20.06L20.06,20.06L20.06,39.94L6,54l14.06,14.06v19.88h19.88L54,102l14.06,-14.06h19.88L87.94,68.06L102,54ZM54,78a24,24 0,1 1,24 -24A24,24 0,0 1,54 78ZM54,36a18,18 0,1 0,18 18A18,18 0,0 0,54 36Z"/>
+</vector>
diff --git a/res/drawable/ic_controller_volume.xml b/res/drawable/ic_controller_volume.xml
new file mode 100644
index 0000000..39b2440
--- /dev/null
+++ b/res/drawable/ic_controller_volume.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M33,32.04L12,32.04a5.99,5.99 0,0 0,-6 5.99v31.93a5.99,5.99 0,0 0,6 5.99L33,75.95v-0.04l23.98,18.63a1.88,1.88 0,0 0,3.03 -1.48L60.01,14.93a1.88,1.88 0,0 0,-3.03 -1.48L33,32.08L33,32.04ZM72.58,26.48 L66.21,32.83a29.89,29.89 0,0 1,0 42.33l6.36,6.35A38.85,38.85 0,0 0,72.58 26.48ZM85.3,13.78 L78.94,20.13a47.82,47.82 0,0 1,0 67.74l6.36,6.35A56.79,56.79 0,0 0,85.3 13.78Z"/>
+</vector>
diff --git a/res/drawable/ic_glare_remove_button_off.xml b/res/drawable/ic_glare_remove_button_off.xml
new file mode 100644
index 0000000..0a07b45
--- /dev/null
+++ b/res/drawable/ic_glare_remove_button_off.xml
@@ -0,0 +1,42 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="75.9dp"
+    android:height="45.9dp"
+    android:viewportWidth="75.9"
+    android:viewportHeight="45.9">
+
+    <path
+        android:fillColor="#E2E2E2"
+        android:pathData="M58.3,35.8H15.6c-7.7,0-14.1-6.3-14.1-14.1v0C1.5,14,7.8,7.7,15.6,7.7h42.7c7.7,0,14.1,6.3,14.1,14.1v0
+C72.3,29.5,66,35.8,58.3,35.8z" />
+    <path
+        android:fillColor="#E2E2E2"
+        android:pathData="M 21.2 2 C 32.1352380466 2 41 10.8647619534 41 21.8 C 41 32.7352380466 32.1352380466 41.6 21.2 41.6 C 10.2647619534 41.6 1.4 32.7352380466 1.4 21.8 C 1.4 10.8647619534 10.2647619534 2 21.2 2 Z" />
+</vector>
diff --git a/res/drawable/ic_glare_remove_button_on.xml b/res/drawable/ic_glare_remove_button_on.xml
new file mode 100644
index 0000000..59ea03b
--- /dev/null
+++ b/res/drawable/ic_glare_remove_button_on.xml
@@ -0,0 +1,42 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="75.9dp"
+    android:height="45.9dp"
+    android:viewportWidth="75.9"
+    android:viewportHeight="45.9">
+
+    <path
+        android:fillColor="#9CC2E7"
+        android:pathData="M58.3,35.8H15.6c-7.7,0-14.1-6.3-14.1-14.1v0C1.5,14,7.8,7.7,15.6,7.7h42.7c7.7,0,14.1,6.3,14.1,14.1v0
+C72.3,29.5,66,35.8,58.3,35.8z" />
+    <path
+        android:fillColor="#5E92CD"
+        android:pathData="M 52.2 2 C 63.1352380466 2 72 10.8647619534 72 21.8 C 72 32.7352380466 63.1352380466 41.6 52.2 41.6 C 41.2647619534 41.6 32.4 32.7352380466 32.4 21.8 C 32.4 10.8647619534 41.2647619534 2 52.2 2 Z" />
+</vector>
diff --git a/res/drawable/ic_media_bigscreen.xml b/res/drawable/ic_media_bigscreen.xml
new file mode 100644
index 0000000..aaab4e4
--- /dev/null
+++ b/res/drawable/ic_media_bigscreen.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M112.9,72.9l7.1,-7.1l-5.8,-5.8l-7.1,7.1L100,60v20h20L112.9,72.9zM67.1,107.1l-7.1,7.1l5.8,5.8l7.1,-7.1L80,120v-20H60L67.1,107.1zM120,100h-20v20l7.1,-7.1l7.1,7.1l5.8,-5.8l-7.1,-7.1L120,100zM65.8,60L60,65.8l7.1,7.1L60,80h20V60l-7.1,7.1L65.8,60z" />
+</vector>
diff --git a/res/drawable/ic_media_cropscreen.xml b/res/drawable/ic_media_cropscreen.xml
new file mode 100644
index 0000000..a867cac
--- /dev/null
+++ b/res/drawable/ic_media_cropscreen.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M60,76h6V66h10v-6H60V76zM66,104h-6v16h16v-6H66V104zM104,60v6h10v10h6V60H104zM114,114h-10v6h16v-16h-6V114zM70,80L60,90l10,10V80zM110,100l10,-10l-10,-10V100zM90,120l10,-10H80L90,120zM80,70h20L90,60L80,70z" />
+</vector>
diff --git a/res/drawable/ic_media_fullscreen.xml b/res/drawable/ic_media_fullscreen.xml
new file mode 100644
index 0000000..51e024b
--- /dev/null
+++ b/res/drawable/ic_media_fullscreen.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M80,60H60v20l7.1,-7.1l7.1,7.1l5.8,-5.8l-7.1,-7.1L80,60zM100,60l7.1,7.1l-7.1,7.1l5.8,5.8l7.1,-7.1L120,80V60H100zM74.2,100l-7.1,7.1L60,100v20h20l-7.1,-7.1l7.1,-7.1L74.2,100zM105.8,100l-5.8,5.8l7.1,7.1L100,120h20v-20l-7.1,7.1L105.8,100z" />
+</vector>
diff --git a/res/drawable/ic_media_live.xml b/res/drawable/ic_media_live.xml
new file mode 100644
index 0000000..d21ce7d
--- /dev/null
+++ b/res/drawable/ic_media_live.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="36dp"
+    android:height="24dp"
+    android:viewportHeight="72.0"
+    android:viewportWidth="108.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:fillAlpha="0.5"
+        android:pathData="M15,0h78c8.3,0 15,6.7 15,15v42c0,8.3 -6.7,15 -15,15H15C6.7,72 0,65.3 0,57V15C0,6.7 6.7,0 15,0z" />
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M24.6,23.2h-5.1v25.6H36v-3.9H24.6V23.2zM44.7,23.2h-5.1v25.6h5.1L44.7,23.2L44.7,23.2zM52.8,23.2h-5.4l8.7,25.6h5.3l8.7,-25.6h-5.4l-5.6,18.7l-0.3,1.4h-0.1l-0.3,-1.4L52.8,23.2zM87,33.6h-9.5v-6.4h11.2v-4H72.4v25.6h16.4v-3.9H77.5v-7.3H87L87,33.6L87,33.6z" />
+</vector>
diff --git a/res/drawable/ic_menu_disabled_forward.xml b/res/drawable/ic_menu_disabled_forward.xml
new file mode 100644
index 0000000..2927aee
--- /dev/null
+++ b/res/drawable/ic_menu_disabled_forward.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:fillAlpha="0.30"
+            android:pathData="M47,22v64l50,-32ZM11,22v64l50,-32Z"/>
+</vector>
diff --git a/res/drawable/ic_menu_disabled_rewind.xml b/res/drawable/ic_menu_disabled_rewind.xml
new file mode 100644
index 0000000..e63a188
--- /dev/null
+++ b/res/drawable/ic_menu_disabled_rewind.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:fillAlpha="0.30"
+            android:pathData="M61,22v64l-50,-32ZM97,22v64l-50,-32Z"/>
+</vector>
diff --git a/res/drawable/ic_menu_disabled_stop.xml b/res/drawable/ic_menu_disabled_stop.xml
new file mode 100644
index 0000000..ee062f2
--- /dev/null
+++ b/res/drawable/ic_menu_disabled_stop.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M58,58h64v64h-64z" />
+</vector>
diff --git a/res/drawable/ic_menu_forward.xml b/res/drawable/ic_menu_forward.xml
new file mode 100644
index 0000000..da3482a
--- /dev/null
+++ b/res/drawable/ic_menu_forward.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M47,22v64l50,-32ZM11,22v64l50,-32Z"/>
+</vector>
diff --git a/res/drawable/ic_menu_rewind.xml b/res/drawable/ic_menu_rewind.xml
new file mode 100644
index 0000000..a044914
--- /dev/null
+++ b/res/drawable/ic_menu_rewind.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="24dp"
+        android:width="24dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M61,22v64l-50,-32ZM97,22v64l-50,-32Z"/>
+</vector>
diff --git a/res/drawable/ic_menu_stop.xml b/res/drawable/ic_menu_stop.xml
new file mode 100644
index 0000000..ee062f2
--- /dev/null
+++ b/res/drawable/ic_menu_stop.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M58,58h64v64h-64z" />
+</vector>
diff --git a/res/drawable/ic_selection.xml b/res/drawable/ic_selection.xml
new file mode 100644
index 0000000..1493b49
--- /dev/null
+++ b/res/drawable/ic_selection.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M3,5 L5,5 L5,3 C3.9,3,3,3.9,3,5 Z M3,13 L5,13 L5,11 L3,11 L3,13 Z M7,21 L9,21
+L9,19 L7,19 L7,21 Z M3,9 L5,9 L5,7 L3,7 L3,9 Z M13,3 L11,3 L11,5 L13,5 L13,3 Z
+M19,3 L19,5 L21,5 C21,3.9,20.1,3,19,3 Z M5,21 L5,19 L3,19 C3,20.1,3.9,21,5,21 Z
+M3,17 L5,17 L5,15 L3,15 L3,17 Z M9,3 L7,3 L7,5 L9,5 L9,3 Z M11,21 L13,21 L13,19
+L11,19 L11,21 Z M19,13 L21,13 L21,11 L19,11 L19,13 Z M19,21
+C20.1,21,21,20.1,21,19 L19,19 L19,21 Z M19,9 L21,9 L21,7 L19,7 L19,9 Z M19,17
+L21,17 L21,15 L19,15 L19,17 Z M15,21 L17,21 L17,19 L15,19 L15,21 Z M15,5 L17,5
+L17,3 L15,3 L15,5 Z M7,17 L17,17 L17,7 L7,7 L7,17 Z M9,9 L15,9 L15,15 L9,15 L9,9
+Z" />
+</vector>
diff --git a/res/drawable/ic_timeline.xml b/res/drawable/ic_timeline.xml
new file mode 100644
index 0000000..7c30ffa
--- /dev/null
+++ b/res/drawable/ic_timeline.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="@color/tab_icon_1"
+        android:pathData="M9.45605,12.4586 L16.2515,12.4586 L16.2515,19.7214 L9.45608,19.7214 Z M20,8 L4,8
+L4,6 L20,6 L20,8 Z M18,2 L6,2 L6,4 L18,4 L18,2 Z M22,12 L22,20
+C22,21.1,21.1,22,20,22 L4,22 C2.9,22,2,21.1,2,20 L2,12 C2,10.9,2.9,10,4,10
+L20,10 C21.1,10,22,10.9,22,12 Z M16,16 L10,12.73 L10,19.26 L16,16 Z" />
+</vector>
diff --git a/res/drawable/ic_vidcontrol_pause.xml b/res/drawable/ic_vidcontrol_pause.xml
new file mode 100644
index 0000000..cd17253
--- /dev/null
+++ b/res/drawable/ic_vidcontrol_pause.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M66,58h16v64H66V58zM98,58h16v64H98V58z" />
+</vector>
diff --git a/res/drawable/ic_vidcontrol_play.xml b/res/drawable/ic_vidcontrol_play.xml
new file mode 100644
index 0000000..d58c6d7
--- /dev/null
+++ b/res/drawable/ic_vidcontrol_play.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="180.0"
+    android:viewportWidth="180.0">
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M70,58v64l50,-32L70,58z" />
+</vector>
diff --git a/res/drawable/ic_vidcontrol_reload.xml b/res/drawable/ic_vidcontrol_reload.xml
new file mode 100644
index 0000000..c0a4284
--- /dev/null
+++ b/res/drawable/ic_vidcontrol_reload.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="60dp"
+    android:height="60dp"
+    android:viewportHeight="144.0"
+    android:viewportWidth="144.0">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M72,42V32L58,46l14,14V50c12.2,0 22,9.8 22,22c0,12.2 -9.8,22 -22,22s-22,-9.8 -22,-22c0,-5.7 2.2,-11 5.8,-14.9l-5.7,-5.6C45.1,56.9 42,64.1 42,72c0,16.6 13.4,30 30,30s30,-13.4 30,-30S88.6,42 72,42z" />
+</vector>
diff --git a/res/drawable/ic_video.xml b/res/drawable/ic_video.xml
new file mode 100644
index 0000000..1904d8b
--- /dev/null
+++ b/res/drawable/ic_video.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:fillColor="@color/tab_icon_3"
+        android:pathData="M18,4 L20,8 L17,8 L15,4 L13,4 L15,8 L12,8 L10,4 L8,4 L10,8 L7,8 L5,4 L4,4
+C2.9,4,2.01,4.9,2.01,6 L2,18 C2,19.1,2.9,20,4,20 L20,20 C21.1,20,22,19.1,22,18
+L22,4 L18,4 Z" />
+</vector>
diff --git a/res/drawable/ic_video_snapshot.xml b/res/drawable/ic_video_snapshot.xml
new file mode 100644
index 0000000..a0d7f45
--- /dev/null
+++ b/res/drawable/ic_video_snapshot.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="36dp"
+        android:width="36dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FF000000"
+            android:fillAlpha="0.50"
+            android:pathData="M54,54m-54,0a54,54 0,1 1,108 0a54,54 0,1 1,-108 0"/>
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M42,36h6v-6h-6V36zM30,72h6v-6h-6V72zM72,30h-6v6h6V30zM60,30h-6v6h6V30zM72,42h-6v6h6V42zM30,60h6v-6h-6V60zM72,66V54h-6v12H54v6h12v10h6V72h10v-6H72zM42,72h6v-6h-6V72zM30,48h6v-6h-6V48zM30,36h6v-6h-6V36z"/>
+</vector>
diff --git a/res/drawable/ic_video_snapshot_padding.xml b/res/drawable/ic_video_snapshot_padding.xml
new file mode 100644
index 0000000..f495b75
--- /dev/null
+++ b/res/drawable/ic_video_snapshot_padding.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<inset
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:drawable="@drawable/ic_video_snapshot"
+        android:insetTop="12dp"
+        android:insetRight="12dp"
+        android:insetBottom="12dp"
+        android:insetLeft="12dp"/>
+
diff --git a/res/drawable/ic_video_snapshot_padding_pressed.xml b/res/drawable/ic_video_snapshot_padding_pressed.xml
new file mode 100644
index 0000000..a66444d
--- /dev/null
+++ b/res/drawable/ic_video_snapshot_padding_pressed.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<inset
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:drawable="@drawable/ic_video_snapshot_pressed"
+        android:insetTop="12dp"
+        android:insetRight="12dp"
+        android:insetBottom="12dp"
+        android:insetLeft="12dp"/>
+
diff --git a/res/drawable/ic_video_snapshot_pressed.xml b/res/drawable/ic_video_snapshot_pressed.xml
new file mode 100644
index 0000000..da65406
--- /dev/null
+++ b/res/drawable/ic_video_snapshot_pressed.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="36dp"
+        android:width="36dp"
+        android:viewportHeight="108.0"
+        android:viewportWidth="108.0">
+    <path
+            android:fillColor="#FF000000"
+            android:fillAlpha="0.26"
+            android:pathData="M54,54m-54,0a54,54 0,1 1,108 0a54,54 0,1 1,-108 0"/>
+    <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M42,36h6v-6h-6V36zM30,72h6v-6h-6V72zM72,30h-6v6h6V30zM60,30h-6v6h6V30zM72,42h-6v6h6V42zM30,60h6v-6h-6V60zM72,66V54h-6v12H54v6h12v10h6V72h10v-6H72zM42,72h6v-6h-6V72zM30,48h6v-6h-6V48zM30,36h6v-6h-6V36z"/>
+</vector>
diff --git a/res/drawable/ic_video_snapshot_selector.xml b/res/drawable/ic_video_snapshot_selector.xml
new file mode 100644
index 0000000..22846e0
--- /dev/null
+++ b/res/drawable/ic_video_snapshot_selector.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_video_snapshot_padding_pressed"
+          android:state_pressed="true" />
+    <item android:drawable="@drawable/ic_video_snapshot_padding" />
+</selector>
+
diff --git a/res/drawable/ic_watermark.xml b/res/drawable/ic_watermark.xml
new file mode 100644
index 0000000..1c57941
--- /dev/null
+++ b/res/drawable/ic_watermark.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25"
+    android:viewportHeight="27">
+
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="2.13350288"
+        android:pathData="M14.9362,15.8471 L14.9362,11.5098
+C16.5957,10.3574,18.5791,8.83929,18.5791,6.57669
+C18.5791,3.01208,15.8574,2,12.5,2 C9.14256,2,6.42093,3.01208,6.42093,6.57669
+C6.42093,8.83929,8.40383,10.3574,10.0633,11.5098 L10.0633,15.8471 L2,17.49 L2,25
+L11.3331,25 L13.6669,25 L23,25 L23,17.49 L14.9362,15.8471 L14.9362,15.8471 Z" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="0.9482235"
+        android:pathData="M3,21 L23,21" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_watermark_emotion.xml b/res/drawable/ic_watermark_emotion.xml
new file mode 100644
index 0000000..bed9457
--- /dev/null
+++ b/res/drawable/ic_watermark_emotion.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="1008"
+    android:viewportHeight="1008">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M910.4,497.6c0,230.6-187.1,417.6-417.7,417.5C264.8,915,75.2,730.5,75.4,497
+C75.7,261.1,270.2,74.7,502.8,80C728.9,85.3,911,271.3,910.4,497.6z
+M493.3,112.1c-210.1-0.4-385.5,170-385.8,385
+c-0.3,214.3,173.7,386,385.4,385.9c214.2-0.1,381.8-173.3,385.5-378.3C882.3,289.8,708.1,112.1,493.3,112.1z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M482.3,742.1c-42.7-0.4-93.1-11.6-138.9-39.9c-29.1-17.9-52.7-41.2-67.1-72.7
+c-7.2-15.8-10.8-32.5-11.1-49.8c-0.2-9.9,6.8-17.5,16.3-18c9.6-0.5,17.5,6.1,17.8,16.2c1.5,42.6,25.7,70.9,59.1,92.9
+c31.5,20.8,66.7,31.1,104,35.2c38.9,4.3,77.2,0.9,114.4-11.2c34-11,64.4-28,87.3-56.4c13.9-17.2,22.1-36.6,22.3-59.1
+c0.1-10.7,7.7-17.9,17.7-17.7c9.9,0.2,16.9,7.7,16.7,18.5c-0.6,34.3-14.2,63.3-37,88.2c-28.3,30.8-63.9,49.5-103.5,61.4
+C551.7,738.3,522.6,742.1,482.3,742.1z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M478.9,398.4c0,51.8-41.8,93.4-93.9,93.4c-51.1,0-92.9-42.1-92.9-93.5c0-51.6,41.9-93.4,93.5-93.4
+C437.2,305,478.9,346.7,478.9,398.4z
+M385.4,336.9c-33.5,0.1-61.5,28.1-61.3,61.5c0.2,33.7,27.9,61.3,61.6,61.2
+c33.6-0.1,61.3-27.8,61.3-61.4C446.9,364.7,418.9,336.9,385.4,336.9z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M600.5,304.9c51.6,0.1,93.5,42,93.4,93.5c-0.1,52.1-42.3,93.8-95.1,93.2c-52.5-0.6-92.6-44.3-91.9-95.4
+C507.7,346.3,549.6,304.8,600.5,304.9z
+M600.7,336.9c-33.4-0.1-61.5,27.6-61.6,60.8c-0.1,34,27.1,61.7,60.8,62
+c33.7,0.3,61.5-27.1,62-60.9C662.4,365.5,634.2,337.1,600.7,336.9z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_watermark_food.xml b/res/drawable/ic_watermark_food.xml
new file mode 100644
index 0000000..a5ecfcc
--- /dev/null
+++ b/res/drawable/ic_watermark_food.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="1008dp"
+    android:height="1008dp"
+    android:viewportWidth="1008"
+    android:viewportHeight="1008">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M222,97.3c35.6,31.4,72.7,63.7,109.2,96.6c36.4,32.8,72.3,66.1,108.2,99.4c19.9,18.4,34.5,40,39.1,67.4
+c3.4,20.9,0.9,41.1-6,61c-0.7,2-1.5,4-2.4,6.6c23.4,21.8,46.8,43.7,70.7,65.9c9.1-8.5,18.1-16.8,27.1-25.2
+c16.9-15.8,33.9-31.5,50.7-47.4c1.2-1.1,2.2-3.8,1.7-5.3c-12.1-38-10.3-76.1,3.2-112.8c32.2-87.6,92.7-146.4,183-172.3
+c37.2-10.7,75-9.9,110.8,7c41.7,19.6,66,53.1,73.6,98.1c7.7,45.9-2.9,88.9-25,129c-33.5,61-82.5,104.9-148.3,128.6
+c-37.9,13.6-76.6,16.4-115.7,3.9c-1.4-0.4-3.8,0-4.7,0.9c-23.5,25-46.8,50.1-70.6,75.6c8.9,8.3,17.6,16.5,26.4,24.6
+c64.7,60.3,129.2,120.8,194.3,180.7c29.8,27.4,31.4,68.2,13.5,95.3c-26.6,40.5-82.3,44.8-115.9,8.8
+C681.2,815.3,617.7,747,554.1,678.7c-4.1-4.4-8.2-8.7-12.6-13.4c-10.5,11.2-20.7,22.1-30.9,33.1
+c-53.9,57.9-107.8,115.9-161.8,173.7c-20.1,21.4-45,29-73.2,21.6c-27.1-7.1-45-25.1-51.7-52.4c-7-28.4,0.9-53,22.4-73
+c68.3-63.6,136.5-127.1,204.8-190.7c1.4-1.3,2.8-2.7,4.5-4.4c-8-8.6-15.8-17-23.6-25.4c-12-12.9-24.2-25.8-36-38.8
+c-2.4-2.7-4.3-3-7.6-1.8c-27.8,10.4-55.8,11.8-83.9,1c-15.3-5.9-28.9-14.8-40-26.7C224.8,438.7,185.1,396,146,352.8
+c-27.7-30.6-54.6-62-81.9-93c-1.1-1.2-2.1-2.5-1.8-2.8C115.3,203.9,168.3,150.9,222,97.3z
+M661,427.1c-1.1,0.8-2.5,1.7-3.7,2.8
+c-36,33.4-72,66.9-107.9,100.4C474.5,600,399.7,669.8,324.9,739.5c-19.6,18.3-39.4,36.3-58.8,54.9c-17,16.3-16.3,42.2,1,58.8
+c16,15.3,42,14.1,57.4-2.5c36.7-39.5,73.5-79,110.3-118.5c75.4-80.9,150.7-161.8,226.1-242.7c10.1-10.8,20.2-21.6,29.7-31.8
+c9,3.6,17.1,7.7,25.6,10.3c30.4,9,60.5,5.9,89.7-4.7c60.5-21.8,104.7-62.4,134.1-119.1c16.5-31.8,25-65.7,18.8-101.8
+c-6.4-37.7-27-64.7-63.4-78.2c-30.7-11.4-61.9-9.1-92.1,1.4c-69.6,24.1-118.4,71.1-146.1,139C640.8,345,638.1,386.2,661,427.1z
+M205.7,157.2c55.8,54.8,111.5,109.6,166.8,164c-5.9,6.2-11.2,11.8-16.9,17.7C300,284.3,244.5,229.7,189.5,175.8
+c-6,6-11.5,11.4-17.1,17.1C227.5,247,283,301.5,337.9,355.5c-6.1,6.2-12,12-18.4,18.4c-54.7-54.7-109.6-109.6-164.2-164.2
+c-4.9,4.9-10,10-15.2,15.2c54.2,55.2,108.7,110.6,162.8,165.7c-5.9,5.9-11.4,11.5-17.3,17.4c-54.4-55.4-109.2-111.1-163.5-166.3
+c-5.5,5.6-10.9,10.9-16.4,16.5c0.6,0.7,1.6,1.9,2.5,3c29.1,32.9,57.9,66.2,87.5,98.7c30.7,33.8,61.6,67.3,93.4,100.1
+c21,21.7,47.5,28.2,76.7,20.2c11.7-3.2,22.7-8.9,34.7-13.7c25.6,27.5,52.2,56,78.9,84.7c12.6-11.7,24.8-23.1,37.3-34.8
+c-29.4-27.4-58.2-54.2-87-81.1c2.2-3.7,4.2-7,5.9-10.4c1.8-3.4,3.5-6.8,4.8-10.4c12.3-31.9,9.4-61.5-14-87.5
+c-8.4-9.4-17.6-18.2-27-26.7c-48.6-44.1-97.4-88-146.2-131.9c-10.4-9.3-21-18.4-31.4-27.5C216.6,146.3,211.4,151.5,205.7,157.2z
+M604.4,597.8c-13.6,14.6-27.1,29.1-40.6,43.6c1.7,1.9,3,3.4,4.4,4.8c44.3,47.5,88.5,95,132.8,142.5c23.3,25,46.5,49.9,69.9,74.8
+c7.8,8.4,17.9,12.1,29.2,12c16.8-0.2,31.6-10.9,37.3-26.3c6-16.1,1.9-32.6-10.9-44.6c-57.6-53.7-115.2-107.4-172.8-161
+C637.3,628.4,620.9,613.2,604.4,597.8z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M908.7,240.1c8.5,16.8,10.8,34.7,8.9,53c-6.6,64.5-59.1,123.9-122.2,138.2c-22.1,5-43.9,4.3-65-5.3
+c-0.7-0.3-1.5-0.8-3.5-1.8c51.7,0,93.1-21,127.5-56.5C888.7,332.3,908.5,290.3,908.7,240.1z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_watermark_location.xml b/res/drawable/ic_watermark_location.xml
new file mode 100644
index 0000000..d430b60
--- /dev/null
+++ b/res/drawable/ic_watermark_location.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+    android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFF" android:pathData="M831.5,356.4c-1,39.1 -8.9,76.5 -21.9,113.3c-16.9,48 -43.4,90.6 -72,132c-33.4,48.6 -68,96.3 -101.6,144.8c-26.1,37.6 -50.8,76.2 -69.5,118.2c-4.3,9.6 -7.8,19.5 -11.3,29.3c-6.2,17.1 -22.2,28.6 -40.5,28.7c-18.3,0.1 -35.1,-11.2 -40.6,-28.5c-11.4,-35.5 -28.8,-68 -48,-99.6c-29.6,-48.9 -63.2,-95.2 -96,-141.9c-28.5,-40.6 -57.1,-81.2 -81.5,-124.5c-22,-38.9 -37.7,-80.1 -44.2,-124.4c-9.3,-62.7 -1.5,-123.5 26.3,-180.6C277.1,128 352.5,67.8 456.6,47.9c102.9,-19.7 194.6,7.3 272.4,77.7c53.7,48.6 85.8,109.7 97.5,181.2C829.2,323.1 829.9,339.8 831.5,356.4zM233.1,360.8c0.3,4.4 0.5,12.9 1.3,21.4c4.1,43.4 17.6,83.8 38.2,122.1c21.9,40.7 48.5,78.4 74.6,116.4c33.7,49 67.8,97.7 100.4,147.4c23.4,35.6 43.6,73.2 56.6,114.2c1.6,5.2 5.5,8 10.3,8c5.3,-0.1 8.7,-2.8 10.5,-7.7c3.2,-8.6 6.1,-17.3 9.7,-25.7c17,-39.8 39.3,-76.7 63.7,-112.3c35.7,-52 72.7,-103.2 108.5,-155.2c28.3,-41 55,-82.8 72.2,-130.2c19,-52.5 24.6,-105.7 13.1,-160.5C760.6,148.2 613.6,50.3 462.8,79.2C329.7,104.7 233.1,221.4 233.1,360.8z"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M368.6,344.7c0,-81.7 65.6,-147 147.6,-147c80.8,0 146.8,66.2 146.7,147.1c-0.1,81.2 -66.1,147.1 -147.3,147.1C434.4,491.9 368.6,426.1 368.6,344.7zM515.3,459.3c63.1,0 114.3,-50.8 115.1,-112.8c0.8,-61.1 -48.4,-116.3 -114.6,-116.5c-63.2,-0.2 -114.9,51.6 -114.9,114.7C400.9,407.8 452.3,459.3 515.3,459.3z"/>
+</vector>
diff --git a/res/drawable/ic_watermark_selected.xml b/res/drawable/ic_watermark_selected.xml
new file mode 100644
index 0000000..736c66b
--- /dev/null
+++ b/res/drawable/ic_watermark_selected.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="25"
+    android:viewportHeight="27">
+
+    <path
+        android:strokeColor="#4592F9"
+        android:strokeWidth="2.13350288"
+        android:pathData="M14.9362,15.8471 L14.9362,11.5098
+C16.5957,10.3574,18.5791,8.83929,18.5791,6.57669
+C18.5791,3.01208,15.8574,2,12.5,2 C9.14256,2,6.42093,3.01208,6.42093,6.57669
+C6.42093,8.83929,8.40383,10.3574,10.0633,11.5098 L10.0633,15.8471 L2,17.49 L2,25
+L11.3331,25 L13.6669,25 L23,25 L23,17.49 L14.9362,15.8471 L14.9362,15.8471 Z" />
+    <path
+        android:strokeColor="#4592F9"
+        android:strokeWidth="0.9482235"
+        android:pathData="M3,21 L23,21" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_watermark_time.xml b/res/drawable/ic_watermark_time.xml
new file mode 100644
index 0000000..9a0b9d8
--- /dev/null
+++ b/res/drawable/ic_watermark_time.xml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="360dp"
+    android:height="360dp"
+    android:viewportWidth="360"
+    android:viewportHeight="360">
+
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="12.2107"
+        android:strokeMiterLimit="10"
+        android:pathData="M180.2,330.3c-83.7,0-151.7-68.1-151.7-151.7
+S96.6,26.8,180.2,26.8s151.7,68.1,151.7,151.7S263.9,330.3,180.2,330.3z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M180.2,57.8c32.3,0,62.6,12.6,85.4,35.4c22.8,22.8,35.4,53.1,35.4,85.4s-12.6,62.6-35.4,85.4
+c-22.8,22.8-53.1,35.4-85.4,35.4s-62.6-12.6-85.4-35.4c-22.8-22.8-35.4-53.1-35.4-85.4S72,115.9,94.8,93.1
+C117.6,70.3,148,57.8,180.2,57.8
+M180.2,52.6c-69.6,0-126,56.4-126,126s56.4,126,126,126s126-56.4,126-126S249.8,52.6,180.2,52.6
+L180.2,52.6z" />
+    <path
+        android:strokeColor="#231F20"
+        android:strokeWidth="16.6991"
+        android:strokeMiterLimit="10"
+        android:pathData="M79.3,177.8" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="16.6991"
+        android:strokeMiterLimit="10"
+        android:pathData="M179.5,278" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="16.6991"
+        android:strokeMiterLimit="10"
+        android:pathData="M179.5,313.3" />
+    <path
+        android:strokeColor="#231F20"
+        android:strokeWidth="16.6991"
+        android:strokeMiterLimit="10"
+        android:pathData="M279.7,177.8" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 179.2 103.7 L 179.2 82.4" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 142.1 113.8 L 131.5 95.3" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 115.1 141.1 L 96.7 130.4" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 105.4 178.2 L 84.1 178.2" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 115.5 215.2 L 97 225.9" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 142.8 242.2 L 132.1 260.7" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 179.9 252 L 179.9 273.3" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 216.9 241.9 L 227.6 260.4" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 243.9 214.6 L 262.4 225.3" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 253.7 177.5 L 275 177.5" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 243.6 140.5 L 262 129.8" />
+    <path
+        android:strokeColor="#231F20"
+        android:strokeWidth="5.5664"
+        android:strokeMiterLimit="10"
+        android:pathData="M 216.3 113.4 L 227 95" />
+    <path
+        android:strokeColor="#231F20"
+        android:strokeWidth="16.6991"
+        android:strokeMiterLimit="10"
+        android:pathData="M 179.5 177.8 H 179.5 V 177.8 H 179.5 V 177.8 Z" />
+    <path
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="12.2107"
+        android:strokeMiterLimit="10"
+        android:pathData="M 179.5 154.2 C 193.307118746 154.2 204.5 165.392881254 204.5 179.2 C 204.5 193.007118746 193.307118746 204.2 179.5 204.2 C 165.692881254 204.2 154.5 193.007118746 154.5 179.2 C 154.5 165.392881254 165.692881254 154.2 179.5 154.2 Z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M179.3,154.5c-2.1,6.6,59.5-80.7,59.5-80.7l-41.2,91.6L179.3,154.5z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_watermark_weather.xml b/res/drawable/ic_watermark_weather.xml
new file mode 100644
index 0000000..d1477ab
--- /dev/null
+++ b/res/drawable/ic_watermark_weather.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="1008dp"
+    android:height="1008dp"
+    android:viewportWidth="1008"
+    android:viewportHeight="1008">
+
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M469.5,958.7c-5.9-13.1-11.4-25.3-17-37.5c-15.2-33-30.7-65.9-45.7-99c-4.8-10.6-11.7-16.6-23.2-20.3
+c-17.3-5.6-33.6-14-50.2-21.6c-3.6-1.7-6.5-2.1-10.1-0.7c-20.3,8.4-40.7,16.5-61,25.1c-29.9,12.7-59.6,25.8-89.4,38.6
+c-1.1,0.5-2.2,0.9-3.9,1.6c0.3-1.5,0.5-2.6,0.8-3.6c15.8-46.6,31.7-93.1,47.4-139.7c2-5.8,3.6-11.7,5.1-17.7
+c0.4-1.7,0.1-4.2-0.9-5.7c-17.1-26.1-30.2-54-39.4-83.8c-0.6-2-2.8-4.3-4.8-5.1c-25.6-9.7-51.2-19.3-76.9-28.7
+c-22.3-8.2-44.7-16.3-67-24.4c-1.2-0.5-2.4-1-4.5-1.9c2.4-1.4,4.3-2.4,6.2-3.4c43.7-23.5,87.4-47.1,131.3-70.5
+c4.4-2.3,6.5-5.1,7.3-10.1c6.6-40,20.9-77.3,42.3-111.7c1.8-3,1.8-5.2,0.4-8.2c-22.2-47.2-44.3-94.5-66.4-141.8
+c-0.7-1.5-1.4-3-2.4-5.2c1.7,0.5,2.9,0.9,4,1.3c49.4,19.4,98.8,38.8,148.2,58.3c3.5,1.4,6.1,1.3,9.5-0.9
+C350,215,394.6,198.4,443,192.2c3.3-0.4,4.5-2.3,5.8-4.7c19.4-37.1,38.7-74.3,58.1-111.4c4.2-8,8.4-16,13.1-25.1
+c2.3,6.8,4.3,12.5,6.2,18.2c14.6,42.9,29.2,85.8,43.7,128.7c1,2.9,2.5,4.3,5.4,5.1c43.1,13.2,81.7,34.7,115.6,64.4
+c2.6,2.3,4.9,3,8.4,2.2c44.3-10.8,88.7-21.3,133-32c10.4-2.5,20.9-5,32.1-7.7c-8.2,12.9-16,25.1-23.8,37.3
+c-22.3,35.1-44.6,70.3-66.9,105.4c-1.9,3-1.9,5.4-0.5,8.6c12.9,30.2,20.9,61.7,23.5,94.5c0.4,5.1,2.2,8.5,6.4,11.3
+c34.6,23.7,69,47.6,103.5,71.5c9.9,6.9,19.9,13.7,30.7,21.1c-10.5,2.8-20.1,5.4-29.7,8c-39.8,10.8-79.6,21.8-119.5,32.4
+c-9.5,2.5-15.7,7.1-19.6,16.9c-8,19.7-19.7,37.6-32.2,54.8c-1.3,1.8-2.1,4.8-1.7,6.8c6,27.3,12,54.6,18.5,81.8
+c6.6,27.8,13.7,55.5,20.6,83.2c0.3,1.1,0.4,2.3,0.7,4.2c-10.3-5.3-20-10.3-29.6-15.2c-35.1-18-70.3-36.1-105.5-53.9
+c-6.2-3.2-12.9-5.6-19.5-8c-1.9-0.7-4.5-0.6-6.3,0.2c-18.5,8.2-37.6,14.6-57.3,19.5c-1.9,0.5-4.2,2-5.2,3.6
+c-12.3,20.7-24.7,41.3-36.5,62.3c-14.5,25.8-28.3,52-42.5,78.1C471.4,955.5,470.7,956.6,469.5,958.7z
+M483.6,789.9
+c161.5-1,284.5-130.3,285.8-282.7c1.4-163.2-129.9-288.8-285.2-289C326.4,217.9,198.1,346,197.9,503.5
+C197.6,661.3,325.9,789.9,483.6,789.9z
+M731.4,813c-7.5-30.4-14.8-59.7-22-89.1c-0.4-0.3-0.8-0.7-1.1-1c-1.4,1.9-2.5,4.4-4.4,5.6
+c-8.9,6-10.1,13.4-6.5,23.2c3.2,8.4,4.5,17.5,6.9,27c-2.1-1.1-3.4-1.7-4.8-2.4c-9.7-5-19.4-10-29.1-14.9c-1.3-0.6-3.2-1.5-4.1-1
+c-5.5,3.4-10.7,7.1-16.2,10.8C677.3,785.2,703.8,798.8,731.4,813z
+M471.9,893.8c14-25.7,27.7-50.8,41.6-76.2c-1.4,0-2.6-0.1-3.7,0
+c-5.8,0.4-12.8-0.9-17,1.9c-4.4,2.9-6.2,9.9-9.1,15.1c-3.3,6-6.6,12.1-10.3,18.8c-1.2-2.4-1.9-4-2.7-5.6
+c-4.2-9.1-8.3-18.2-12.5-27.3c-0.6-1.3-2-2.9-3.3-3.1c-6.2-1-12.4-1.5-18.9-2.2C447.9,841.4,459.8,867.3,471.9,893.8z
+M217,792.8
+c27.5-11.9,53.9-23.3,80.7-34.8c-4.5-3.5-8.8-6.7-12.8-10.2c-2.2-1.9-4.1-2.2-6.8-1c-8.7,4-17.5,7.7-26.3,11.5
+c-1.2,0.5-2.5,0.9-4.5,1.6c3.9-11.3,7.4-21.6,10.9-31.9c0.4-1.4,0.6-3.5-0.1-4.4c-3.9-4.7-8.2-9-12.7-13.9
+C235.9,737.4,226.6,764.5,217,792.8z
+M786.5,590.1c27.7-7.4,54.6-14.7,82.6-22.2c-24.3-16.6-47.5-32.6-71.1-48.7
+c-0.4,5.5-0.5,10.3-1.3,15c-0.7,4.3,0.7,6.8,4.4,9.1c8.4,5.3,16.5,11.2,25.2,17.2c-1.5,0.5-2.3,0.9-3.1,1.1
+c-9.5,2.6-19.1,5-28.5,7.8c-1.5,0.4-3.4,1.7-3.7,3C789.3,577.9,788.1,583.6,786.5,590.1z
+M718.8,294.8c2.4,2.9,4.6,4.8,6,7.2
+c4.1,7.2,9.4,8.9,17.3,5.8c6.1-2.3,12.8-3.2,20.2-4.9c-5.5,8.6-10.3,16.1-15,23.7c-0.7,1.2-1.2,3.3-0.7,4.3c2.9,5,6.1,9.9,9.5,15.2
+c15.1-23.7,30-47.1,45.5-71.4C773.5,281.5,746.5,288.1,718.8,294.8z
+M143.3,526.3c8.1-4.3,15.5-8.3,22.8-12.3
+c1.2-0.7,2.9-1.9,3-2.9c0.3-6.1,0.1-12.3,0.1-19.1c-23.6,12.6-46.3,24.8-69.9,37.5c25.2,9.2,49.3,17.9,74,26.9
+c-0.8-5.6-1.7-10.6-2-15.6c-0.2-3.4-1.5-5-4.6-6C159.1,532.2,151.6,529.3,143.3,526.3z
+M205.7,237.1c-0.3,0.3-0.5,0.5-0.8,0.8
+c10.8,23.1,21.7,46.2,32.8,69.8c2.9-3.5,4.9-6.6,7.6-8.9c5-4.2,5.1-8.4,1.8-13.8c-2.7-4.4-4.5-9.4-7.1-15.1
+c7.7,3,14.3,5.6,20.8,8.1c1.1,0.4,3,0.7,3.6,0.2c4.6-4,8.9-8.2,13.6-12.7C253.5,255.9,229.6,246.5,205.7,237.1z
+M538.1,193.9
+c-7.9-23.2-15.6-45.9-23.6-69.7c-11.5,22.1-22.5,43.2-34,65.3c5.8,0,10.5-0.4,15.2,0.1c4,0.4,5.9-1,7.4-4.5c2.1-4.8,4.9-9.4,7.8-15
+c2.3,6.8,4.2,12.6,6.3,18.3c0.4,1.1,1.3,2.7,2.2,2.8C525.5,192.2,531.5,193,538.1,193.9z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/icn_media_forward.xml b/res/drawable/icn_media_forward.xml
new file mode 100644
index 0000000..374ca5d
--- /dev/null
+++ b/res/drawable/icn_media_forward.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_menu_forward" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_menu_disabled_forward" />
+</selector>
diff --git a/res/drawable/icn_media_rewind.xml b/res/drawable/icn_media_rewind.xml
new file mode 100644
index 0000000..b606637
--- /dev/null
+++ b/res/drawable/icn_media_rewind.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_menu_rewind" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_menu_disabled_rewind" />
+</selector>
diff --git a/res/drawable/icn_media_stop.xml b/res/drawable/icn_media_stop.xml
new file mode 100644
index 0000000..31d8555
--- /dev/null
+++ b/res/drawable/icn_media_stop.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_menu_stop" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_menu_disabled_stop" />
+</selector>
diff --git a/res/drawable/icon_artistic_sun.xml b/res/drawable/icon_artistic_sun.xml
new file mode 100644
index 0000000..46ad53e
--- /dev/null
+++ b/res/drawable/icon_artistic_sun.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M323,267.8c0,0,0.1-0.1,0.1-0.1c-3.5-2.8-6.8-5.7-10.4-8.3c-12-8.4-25.4-13.8-39.4-18.1
+			c-28.3-8.6-57.4-11.9-86.9-12.3c-16.4-0.2-32.7,0.7-48.9,2.8c-17.7,2.3-35,5.8-51.8,11.6c-12.2,4.2-24,9.4-34.4,17.2
+			c-2.7,2-5.1,4.2-7.6,6.3c0.1,0.1,0.2,0.2,0.2,0.4c0.4-0.1,0.8-0.2,1.2-0.4c10.7-5,21.9-9,33.3-12.2c33-9.2,66.7-13,100.9-13.3
+			c23.2-0.2,46.2,1.3,69.1,4.9c19.6,3.1,38.9,7.5,57.6,14.5C311.7,263,317.3,265.5,323,267.8 M120.6,221.9
+			c0.2-16.4,5.9-30.7,17.5-42.5c11.7-11.8,26-18.2,42.9-18.8c15.5-0.6,29.4,3.9,41.4,13.4c15.5,12.3,23.2,28.4,23.6,47.9
+			c2.9,0.6,5.6,1.1,8.3,1.6c0.3,0.1,0.9-0.4,1.1-0.8c0.2-0.5,0.2-1.2,0.2-1.7c-0.2-11.4-2.9-22.1-8.3-32.2
+			c-14.3-26.4-43.6-41.2-74-37.1c-16.5,2.2-30.7,9.3-42.2,21.1c-13.1,13.4-19.7,29.5-20.1,48.1c0,0.9,0.2,1.8,0.3,2.8
+			C114.6,223,117.6,222.4,120.6,221.9 M138.5,219.2c1.6-22.7,19.7-39.3,40.6-41.1c12.5-1.1,23.7,2.4,33.3,10.4
+			c9.6,8.1,14.7,18.4,15.6,30.7c3.3,0.4,6.4,0.9,9.8,1.3c-1.4-20.5-10.5-36.3-29-45.7c-20.5-10.5-40.7-8.6-59.2,5.1
+			c-13.5,10-20.1,23.9-20.9,40.5c0.7,0,1.2,0,1.6-0.1C133,219.9,135.7,219.6,138.5,219.2 M99.9,86.6c0.5,17.1,4.4,33,15.8,46.6
+			c7.3,8.7,16.5,14.8,27.3,18.9c1.8-6.8,3.3-13.3,3-20.1c-0.3-6.9-3.3-12.3-8.9-16.4c-2.8-2.1-5.8-3.9-8.8-5.7
+			c-6.4-3.9-12.9-7.7-18.3-12.9C106.5,93.7,103.4,90.1,99.9,86.6 M40.1,139.6c0.4,0.7,0.7,1.1,1,1.5c4.1,5.8,8.6,11.3,13.9,16.2
+			c16.2,15.1,35.4,22,57.7,20.3c0.5,0,1-0.2,1.6-0.4c-2-6.1-4.2-11.9-7.7-17.2c-4.1-6.3-9.7-10.4-17.3-11.4c-4.3-0.6-8.6-1-13-1.2
+			c-9.6-0.6-19.2-1.7-28.3-4.9C45.4,141.6,42.9,140.6,40.1,139.6 M324.4,139.7c-0.4,0.2-0.8,0.3-1.2,0.5c-7.7,3.3-15.7,5.5-24.1,6.3
+			c-6.5,0.6-13,1.1-19.6,1.6c-10.1,0.7-17.8,5.2-22.5,14.1c-2.2,4.2-3.9,8.6-5.8,13c-0.3,0.7-0.5,1.5-0.7,2.4
+			c12.1,1.2,23.7-0.1,34.8-4.5C302.3,166.3,314.6,154.5,324.4,139.7 M180.8,66.3c-1.7,3.1-3.4,6.1-4.9,9.1c-4.9,9.9-8,20.2-8,31.3
+			c0,12.9,4.5,24.3,12.6,34.4c0.3,0.4,0.7,0.7,1,1.1c5.4-5.1,10.5-10.2,14.1-16.5c3.4-5.9,3.8-12,1-18.3c-1.1-2.5-2.3-4.9-3.6-7.2
+			c-3.5-6.2-7-12.5-8.9-19.3C182.8,76.2,181.9,71.3,180.8,66.3 M265.2,86.7l-0.6-0.1c-0.1,0.1-0.3,0.2-0.4,0.3
+			c-6.8,9.1-15.6,15.9-25.5,21.7c-3.9,2.3-7.8,4.7-11.4,7.4c-4.1,3-6.9,6.9-7.9,11.9c-1.1,5.1-0.7,10.2,0.3,15.2c0.5,3,1.3,5.9,2,9
+			c0.5-0.2,0.8-0.2,1-0.3c10-4,18.8-9.8,25.8-17.9c8.2-9.4,12.8-20.5,14.8-32.6C264.3,96.4,264.6,91.5,265.2,86.7 M103.6,212.7
+			c-0.4-0.5-0.6-0.7-0.7-0.9c-4.9-4.2-10-8.1-15.8-11.1c-6-3-12.3-4.7-18.9-2.9c-4.9,1.3-9.7,3.2-14.3,5.3c-9.3,4-18.7,7.4-28.9,8.7
+			c-2.2,0.3-4.4,0.5-7,0.7c0.6,0.3,0.8,0.5,1.1,0.7c7.1,3.4,14.5,6.3,22.2,8.2c16.8,4.3,33.4,4.2,49.6-2.5
+			C95.2,217.2,99.3,214.8,103.6,212.7 M261.4,212.2c0.3,0.3,0.4,0.4,0.6,0.5c15.1,9.7,31.7,13.1,49.6,11c11.6-1.4,22.5-5,32.9-9.9
+			c0.7-0.3,1.4-0.7,2.5-1.2c-0.9-0.1-1.3-0.2-1.6-0.2c-9.5-0.6-18.7-2.8-27.5-6.4c-5.7-2.3-11.3-4.8-17-7c-4.5-1.7-9.3-2.3-14.1-1.4
+			C276.7,199.6,269.1,205.9,261.4,212.2 M146.7,218.3c2.7-0.2,5-0.5,7.3-0.5c1.9,0,2.7-0.6,3.1-2.5c3.1-13,16.6-21.8,30-19.7
+			c11.4,1.8,20,9.7,22.6,20.8c0.1,0.5,0.6,1.1,1,1.2c2.9,0.3,5.9,0.5,8.8,0.8c0-8.3-5.7-20.7-17.2-27.2c-12.8-7.3-25.8-7.3-38.5,0.3
+			C153.7,197.4,148.2,206.6,146.7,218.3"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M323,267.8c-5.7-2.3-11.3-4.8-17-6.9c-18.6-7-37.9-11.4-57.6-14.5c-22.9-3.6-45.9-5.1-69.1-4.9
+			c-34.2,0.3-67.9,4.1-100.9,13.3C67,258,55.9,262,45.1,267c-0.4,0.2-0.8,0.3-1.2,0.4c-0.1-0.1-0.2-0.2-0.2-0.4
+			c2.5-2.1,5-4.4,7.6-6.3c10.4-7.7,22.1-12.9,34.4-17.2c16.8-5.8,34.2-9.4,51.8-11.6c16.2-2.1,32.5-3,48.9-2.8
+			c29.5,0.4,58.6,3.7,86.9,12.3c14,4.2,27.4,9.7,39.4,18.1c3.6,2.6,7,5.5,10.4,8.3C323.1,267.7,323,267.8,323,267.8"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M120.6,221.9c-3.1,0.6-6.1,1.2-9.3,1.8c-0.1-1-0.4-1.9-0.3-2.8c0.4-18.5,7-34.7,20.1-48.1
+			c11.5-11.8,25.7-18.9,42.2-21.1c30.4-4.1,59.7,10.6,74,37.1c5.5,10.1,8.1,20.8,8.3,32.2c0,0.6,0,1.2-0.2,1.7
+			c-0.2,0.4-0.8,0.8-1.1,0.8c-2.8-0.5-5.5-1-8.3-1.6c-0.5-19.5-8.1-35.6-23.6-47.9c-12-9.5-25.9-13.9-41.4-13.4
+			c-16.8,0.6-31.2,6.9-42.9,18.8C126.5,191.1,120.8,205.4,120.6,221.9"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M138.5,219.2c-2.8,0.4-5.4,0.8-8.1,1.1c-0.4,0.1-0.9,0.1-1.6,0.1c0.8-16.7,7.4-30.5,20.9-40.5
+			c18.5-13.7,38.7-15.6,59.2-5.1c18.5,9.5,27.6,25.3,29,45.7c-3.4-0.5-6.5-0.9-9.8-1.3c-1-12.3-6-22.7-15.6-30.7
+			c-9.6-8-20.8-11.5-33.3-10.4C158.1,179.9,140.1,196.5,138.5,219.2"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M99.9,86.6c3.4,3.6,6.6,7.2,10.1,10.4c5.4,5.2,11.9,9,18.3,12.9c3,1.8,6,3.6,8.8,5.7
+			c5.6,4.1,8.5,9.5,8.9,16.4c0.3,6.8-1.2,13.3-3,20.1c-10.8-4.2-20-10.2-27.3-18.9C104.3,119.6,100.4,103.7,99.9,86.6"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M40.1,139.6c2.8,1,5.3,2,7.9,2.9c9.2,3.2,18.7,4.3,28.3,4.9c4.3,0.3,8.7,0.6,13,1.2
+			c7.6,1.1,13.2,5.2,17.3,11.5c3.4,5.3,5.6,11,7.7,17.2c-0.6,0.1-1.1,0.4-1.6,0.4c-22.4,1.7-41.6-5.2-57.7-20.3
+			c-5.2-4.9-9.8-10.3-13.9-16.2C40.8,140.7,40.5,140.3,40.1,139.6"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M324.4,139.7c-9.8,14.8-22.1,26.7-39.1,33.4c-11.1,4.4-22.7,5.7-34.8,4.5c0.3-0.9,0.4-1.7,0.7-2.4
+			c1.9-4.3,3.5-8.8,5.8-13c4.7-8.9,12.4-13.3,22.5-14.1c6.5-0.5,13.1-0.9,19.6-1.6c8.4-0.8,16.4-3.1,24.1-6.3
+			C323.6,139.9,324,139.8,324.4,139.7"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M180.8,66.3c1.1,5,1.9,9.9,3.2,14.6c1.9,6.9,5.5,13.1,8.9,19.3c1.3,2.4,2.5,4.8,3.6,7.2
+			c2.8,6.2,2.3,12.3-1,18.3c-3.6,6.3-8.6,11.4-14.1,16.5c-0.4-0.4-0.7-0.7-1-1.1c-8-10.1-12.5-21.5-12.6-34.4c0-11.1,3-21.4,8-31.3
+			C177.5,72.4,179.2,69.4,180.8,66.3"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M265.2,86.7c-0.6,4.8-0.9,9.7-1.7,14.5c-2,12.1-6.7,23.1-14.8,32.6c-7,8.1-15.8,13.9-25.8,17.9
+			c-0.2,0.1-0.5,0.1-1,0.3c-0.7-3.1-1.5-6-2-9c-0.9-5-1.4-10.1-0.3-15.2c1.1-5,3.8-8.9,7.9-11.9c3.7-2.6,7.5-5.1,11.4-7.4
+			c9.8-5.8,18.6-12.6,25.5-21.7c0.1-0.1,0.2-0.2,0.4-0.3L265.2,86.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M103.6,212.7c-4.3,2.2-8.4,4.5-12.7,6.3c-16.2,6.7-32.8,6.7-49.6,2.5c-7.7-1.9-15-4.8-22.2-8.2
+							c-0.3-0.1-0.5-0.3-1.1-0.7c2.6-0.3,4.8-0.5,7-0.7c10.1-1.2,19.6-4.6,28.9-8.7c4.7-2,9.4-3.9,14.3-5.3c6.6-1.8,13-0.2,18.9,2.9
+							c5.8,3,10.9,6.9,15.8,11.1C103.1,211.9,103.2,212.1,103.6,212.7"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M261.4,212.2c7.7-6.3,15.3-12.6,25.4-14.6c4.8-1,9.6-0.3,14.1,1.4c5.7,2.2,11.3,4.7,17,7
+			c8.8,3.6,18,5.7,27.5,6.4c0.4,0,0.7,0.1,1.6,0.2c-1.1,0.6-1.8,0.9-2.5,1.2c-10.5,4.9-21.4,8.5-32.9,9.9
+			c-17.9,2.1-34.5-1.3-49.6-11C261.8,212.6,261.7,212.5,261.4,212.2"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M146.7,218.3c1.5-11.7,7-20.9,17.1-26.9c12.6-7.6,25.7-7.6,38.5-0.3c11.5,6.5,17.2,18.9,17.2,27.2
+			c-2.9-0.2-5.9-0.5-8.8-0.8c-0.4,0-0.9-0.7-1-1.2c-2.6-11.1-11.2-19-22.6-20.8c-13.4-2.1-26.9,6.7-30,19.7
+			c-0.5,1.9-1.3,2.5-3.1,2.5C151.7,217.8,149.4,218.1,146.7,218.3"/>
+</vector>
diff --git a/res/drawable/icon_calendar.xml b/res/drawable/icon_calendar.xml
new file mode 100644
index 0000000..594eb33
--- /dev/null
+++ b/res/drawable/icon_calendar.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M137,60.4c29.4,0 58.5,0 87.7,0c0,0.8 0,1.4 0,2c0,7.2 -0.1,14.5 0.1,21.8c0.3,10.8 9.5,19.5 20.5,19.5c10.8,0 20.1,-8.6 20.5,-19.3c0.3,-7.2 0.1,-14.5 0.1,-21.8c0,-0.7 0,-1.4 0,-2.3c0.8,0 1.5,0 2.2,0c6.9,0 13.8,0 20.7,0c10.4,0 18.6,8.1 18.8,18.4c0,0.3 0,0.6 0,0.9c0,68.6 0,137.2 0,205.8c0,15.3 -10.1,27.5 -25.1,30.4c-1.8,0.4 -3.8,0.5 -5.6,0.5c-63.9,0 -127.8,0 -191.7,0c-17.4,0 -30.7,-13.3 -30.7,-30.7c0,-68.8 0,-137.5 0,-206.3c0,-11 8,-19 19,-19c6.8,0 13.5,0 20.3,0c0.7,0 1.3,0 2.2,0c0,0.9 0,1.6 0,2.3c0,6.8 0,13.6 0,20.5c0,11.4 9.2,20.6 20.6,20.6s20.6,-9.2 20.6,-20.6c0,-6.9 0,-13.8 0,-20.7C137,61.8 137,61.2 137,60.4zM287,146c-70.8,0 -141.5,0 -212.2,0c0,0.8 0,1.4 0,2.1c0,45.7 0,91.5 0,137.2c0,6.4 4.1,10.6 10.5,10.6c63.8,0 127.6,0 191.3,0c6.3,0 10.5,-4.2 10.5,-10.4c0,-45.8 0,-91.6 0,-137.4C287,147.4 287,146.7 287,146z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M234.8,61.1c0,-7.1 0,-14.2 0,-21.2c0,-6.3 4.4,-11 10.4,-11.1c5.9,-0.1 10.6,4.6 10.6,10.9c0,14.3 0,28.6 0,43c0,6.4 -4.7,11.1 -10.8,11c-5.9,-0.1 -10.4,-4.9 -10.4,-11.2C234.8,75.3 234.8,68.2 234.8,61.1z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M105.9,61.1c0,-7.1 0,-14.3 0,-21.4c0,-6.2 4.4,-10.8 10.4,-10.9c5.9,-0.1 10.5,4.5 10.6,10.7c0.1,7 0,13.9 0,20.9c0,7.5 0,15 0,22.5c0,4.5 -2,7.9 -6.1,9.8c-3.8,1.8 -7.5,1.4 -10.8,-1.2c-2.7,-2 -4.1,-4.8 -4.1,-8.2C105.9,75.9 105.9,68.5 105.9,61.1z"/>
+</vector>
diff --git a/res/drawable/icon_cheers.xml b/res/drawable/icon_cheers.xml
new file mode 100644
index 0000000..799f015
--- /dev/null
+++ b/res/drawable/icon_cheers.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M200.8,22.8c-0.7,0.2-1.1,0.3-1.6,0.4c-2.8,0.9-5.7,1.8-8.4,2.7c-0.9,0.3-1.5,0.1-2.1-0.4
+			c-2.4-1.8-4.7-3.6-7.1-5.5c-0.3-0.3-0.7-0.5-1.2-0.8c0,3.6,0,7.1,0,10.5c0,0.8-0.2,1.3-0.9,1.7c-1.4,0.9-2.8,1.9-4.2,2.8
+			c-1.5,1-2.9,2-4.6,3.2c3.1,1,6,2,8.9,2.9c1.6,0.4,2.6,1.1,2.9,2.9c0.4,1.9,1.1,3.8,1.6,5.7c0.3,1.1,0.6,2.1,1.1,3.4
+			c2.2-2.9,4.2-5.7,6.2-8.5c0.5-0.7,1-0.9,1.9-0.9c3.4,0.1,6.8,0,10.3,0c-0.2-0.3-0.4-0.6-0.6-1c-1.2-1.7-2.3-3.6-3.8-5.1
+			c-2-2.1-2.3-4.2-1-6.8C199.3,27.8,199.9,25.4,200.8,22.8z M184.3,111c4.7,19.5,9.4,38.7,13.9,58c1.7,7.1,5,13.3,10.3,18.3
+			c8.2,7.9,18.2,11.5,29.7,10.7c3.6-0.2,5.6,1.2,6.6,4.7c4.5,15.6,8.9,31.3,13.4,47c0.5,1.8,0.5,3.6-0.6,5c-1.3,1.8-2.7,3.6-4.4,5
+			c-3.8,3.1-8.3,5-12.9,6.6c-1.9,0.7-2.6,1.5-2.1,2.6c0.4,1.1,1.4,1.3,3.3,0.8c9.7-3,19.4-6.1,29.1-9.1c8.2-2.6,16.3-5.1,24.5-7.7
+			c0.3-0.1,0.6-0.2,0.9-0.3c1.1-0.4,1.7-1.1,1.4-2.2c-0.3-1.2-1.2-1.3-2.3-1.1c-3.2,0.7-6.4,1.5-9.6,1.9c-3.6,0.5-7.2,0.6-10.7-0.6
+			c-2.5-0.8-4.2-2.4-5-5c-0.7-2.3-1.5-4.5-2.3-6.7c-4.7-13.1-9.3-26.2-14-39.3c-1.1-3.2-0.3-5.6,2.6-7.4c6.2-4,10.9-9.3,13.9-16
+			c4.1-9.2,4.9-18.6,1.2-28c-6.3-16.1-12.9-32.1-19.3-48.2c-1.2-2.9-2.4-5.9-3.6-8.9C226.8,97.7,205.6,104.3,184.3,111z M126,51.7
+			c-0.3,0.6-0.5,1.1-0.6,1.6c-6.8,17.2-13.6,34.5-20.4,51.7c-1.7,4.3-3.3,8.5-3.6,13.1c-0.7,15.3,5.4,27.1,18.4,35.3
+			c3.5,2.2,4.4,4.3,3,8.3c-5.2,14.8-10.4,29.5-15.3,44.3c-1.4,4-3.9,6-7.8,6.6c-4.5,0.7-8.9,0.2-13.3-0.7c-1.6-0.3-3.1-0.8-4.6-1.1
+			c-1.1-0.3-2.1,0.2-2.3,1.2c-0.2,1.1,0.3,1.8,1.3,2.1c0.4,0.1,0.9,0.3,1.3,0.4c13,4,26,8,39.1,12c5,1.5,9.9,3,14.9,4.6
+			c1,0.3,1.9,0.4,2.6-0.6c0.6-1,0.1-2-1.3-2.6c-3.1-1.3-6.2-2.5-9.2-4c-3.2-1.6-6.1-3.6-8.2-6.5c-1.4-2-1.9-4.1-1.2-6.6
+			c4.3-15.2,8.6-30.4,12.7-45.7c1.4-5.2,3.2-6.2,8.2-6.3c14.3-0.3,25.2-6.7,32.7-18.8c2.8-4.5,3.9-9.6,5.1-14.7
+			c0.9-3.7,2-7.3,0.4-11.2c-0.5-1.2-0.7-2.5-1-3.8c-0.3-1.3-0.6-2.7-0.9-4.1c1.9-0.6,3.6-1.2,5.3-1.7c0.9-0.2,1.2-0.7,1.4-1.5
+			c1.7-7.5,3.5-15,5.2-22.5c0.7-3.1,1.4-6.1,2.1-9.3C168.5,64.7,147.3,58.2,126,51.7z M182.6,134.7c-7.9,20.1-22.5,30.4-44.1,31.4
+			c-0.6,2.1-1.2,4.4-1.9,6.6c-3.6,13-7.2,26.1-10.9,39.1c-0.4,1.2,0.2,1.8,1,2.5c2.9,2.5,6.3,4.2,9.8,5.6c1.1,0.4,2.2,0.8,3.4,1.2
+			c4.7,1.7,7.1,6.5,5.7,11.1c-1.5,4.6-6.4,7.2-11.1,5.8c-13.9-4.2-27.7-8.5-41.6-12.8c-4.9-1.5-9.9-3-14.8-4.6
+			c-3.8-1.2-6.2-4.9-5.9-8.7c0.2-4.1,2.9-7.5,6.9-8.2c1.6-0.3,3.4-0.1,5.1,0.3c4.2,1,8.3,1.9,12.5,1.7c0.3,0,0.5,0,0.8,0
+			c1.7-0.1,2.6-0.7,3.3-2.5c4.8-14.1,9.7-28.1,14.6-42.2c0.4-1.2,0.1-1.7-0.9-2.4c-14.6-10-21.3-23.9-20.3-41.5
+			c0.3-5.5,2.3-10.5,4.3-15.5c7.6-19.1,15.2-38.4,22.8-57.5c0.1-0.4,0.3-0.7,0.5-1.2c20.2,6.2,40.4,12.4,60.7,18.7
+			c-0.1-0.5-0.1-0.8-0.2-1.1c-1.4-4.7-2.8-9.4-4.2-14.1c-0.3-1-0.8-1.5-1.8-1.8c-5.3-1.7-10.5-3.4-15.7-5c-0.3-0.1-0.6-0.2-1.2-0.4
+			c0.5-0.4,0.9-0.7,1.2-0.9c4.5-3.1,9-6.2,13.6-9.2c0.9-0.6,1.1-1.1,1.1-2.1c-0.1-5.4,0-10.9,0-16.3V9c2.8,2.2,5.4,4.1,8.1,6.1
+			c2.2,1.7,4.3,3.4,6.5,4.9c0.4,0.3,1.2,0.4,1.7,0.3c5.7-1.8,11.4-3.6,17.4-5.5c-0.2,0.6-0.3,1-0.4,1.5c-1.8,5.1-3.6,10.2-5.5,15.3
+			c-0.3,0.9-0.3,1.5,0.3,2.4c3.5,4.7,6.9,9.5,10.5,14.3c-2,0-3.9,0-5.8,0c-4.2-0.1-8.4-0.2-12.6-0.3c-0.4,0-0.9,0.1-1.1,0.4
+			c-3.4,4.5-6.7,9-10.1,13.7c4.8,1.5,9.4,2.9,14.2,4.4c-2.7,11.7-5.4,23.3-8.2,35.2c20.8-6.5,41.4-13,62.1-19.5
+			c1.7,4.2,3.3,8.2,4.9,12.3c6.9,17.1,13.8,34.1,20.5,51.2c3.5,9,3.5,18.3,0.8,27.6c-2.9,9.9-8.7,17.8-17.2,23.8
+			c-0.8,0.6-0.9,1-0.6,1.9c5.2,14.6,10.4,29.2,15.5,43.8c0.3,0.8,0.8,1.1,1.6,1.3c3.7,0.7,7.4,0.1,11-0.7c1.8-0.4,3.5-0.9,5.3-1.3
+			c4.6-0.8,9,2,10.1,6.5c1.2,4.5-1.3,9.2-5.7,10.6c-10.8,3.5-21.7,6.8-32.5,10.2c-7.8,2.5-15.5,4.9-23.3,7.3
+			c-4.4,1.4-8.8-0.4-10.9-4.3c-1.9-3.7-1-8.4,2.4-11c0.9-0.7,2-1.2,3.1-1.6c4.2-1.6,8.4-3.3,11.9-6.2c2-1.6,2-1.7,1.3-4.1
+			c-4.1-14.3-8.2-28.5-12.2-42.8c-0.3-1.2-0.8-1.5-2-1.5c-20,0.7-38.6-12.3-44.3-31.2c-2-6.6-3.3-13.3-4.9-20
+			C185.7,147.7,184.2,141.4,182.6,134.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M220.3,53.6c-1.8,1.8-3.4,3.5-4.9,5.2c-0.6,0.6-1.1,0.9-2,0.7c-2.3-0.4-4.6-0.7-7-1.1c0,0.3,0,0.4,0.1,0.4
+			c0.7,1.3,1.2,2.7,2.1,3.8c1.7,2.2,1.6,4.2,0,6.4c-0.9,1.2-1.4,2.7-2.2,4.3c2.3-0.4,4.3-0.7,6.2-1.2c1.5-0.4,2.6-0.2,3.7,1.1
+			c0.9,1.1,2,2.1,3.1,3.1c0.4,0.4,0.9,0.8,1.4,1.3c0.3-2.5,0.7-4.6,0.9-6.8c0.1-1.3,0.6-1.8,1.7-2.3c2-0.9,3.9-2,6-3.1
+			c-2.4-1.1-4.4-2.2-6.5-3c-1-0.4-1.3-1-1.4-2C221.1,58.3,220.7,56.1,220.3,53.6z M196.7,51.9c4.9,0.8,9.6,1.5,14.2,2.2
+			c1.1,0.2,1.8,0.1,2.6-0.8c3.2-3.5,6.5-6.9,10-10.5c0.3,2,0.6,3.7,0.9,5.4c0.5,3.1,1,6.1,1.5,9.2c0.1,0.8,0.4,1.3,1.2,1.6
+			c4.2,1.9,8.3,3.9,12.5,5.8c0.3,0.1,0.5,0.3,0.9,0.5c-0.4,0.3-0.7,0.5-1,0.6c-4,2.1-8.1,4.1-12.1,6.2c-0.7,0.4-1.1,0.8-1.2,1.7
+			c-0.5,4.6-1.2,9.1-1.8,13.7c0,0.3-0.1,0.5-0.1,1c-1.4-1.3-2.6-2.5-3.9-3.7c-2.2-2.2-4.4-4.3-6.5-6.5c-0.7-0.7-1.3-0.9-2.3-0.7
+			c-4.3,0.9-8.7,1.7-13,2.5c-0.4,0.1-0.9,0.1-1.5,0.1c2.2-4.4,4.4-8.7,6.6-12.9c0.5-0.9,0.5-1.6,0-2.5c-2.1-3.7-4.2-7.5-6.2-11.3
+			C197.3,53,197.1,52.6,196.7,51.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M179,182.6c-0.6-2-1.1-3.6-1.5-5.2c-0.1-0.5,0.1-1.3,0.4-1.7c1-1.4,2.1-2.7,3.2-4c-0.1-0.1-0.1-0.3-0.2-0.4
+			c-1.6,0-3.3-0.1-4.9,0c-1,0.1-1.5-0.3-2-1.1c-0.8-1.4-1.8-2.7-2.8-4.3c-0.6,1.8-1.3,3.3-1.7,4.9c-0.3,0.9-0.8,1.3-1.7,1.5
+			c-1.6,0.4-3.2,0.8-5,1.3c1.3,1,2.4,2,3.5,2.6c1.4,0.8,1.7,1.9,1.5,3.4c-0.2,1.3-0.2,2.7-0.3,4.3c1.6-1.1,2.9-1.8,4.1-2.8
+			c0.9-0.7,1.7-0.8,2.8-0.3C175.8,181.5,177.3,182,179,182.6z M154.2,171.9c3.8-1,7.3-2,10.8-2.8c0.8-0.2,1.2-0.6,1.5-1.4
+			c1.2-3.4,2.4-6.8,3.7-10.4c1.5,2.3,3.1,4.3,4.2,6.6c1.5,3,3.5,4.3,6.9,3.9c2.5-0.3,5-0.1,7.5-0.1c0.1,0.1,0.1,0.3,0.1,0.4
+			c-0.5,0.6-0.9,1.2-1.4,1.8c-1.8,2.2-3.6,4.4-5.4,6.6c-0.5,0.6-0.6,1.2-0.4,2c1.1,3.4,2.1,6.9,3.1,10.5c-0.6-0.2-1-0.3-1.4-0.4
+			c-3-1.2-6.1-2.4-9.2-3.4c-0.5-0.2-1.3-0.1-1.8,0.2c-2.6,1.7-5.2,3.5-7.8,5.3c-0.4,0.3-0.9,0.6-1.5,1c0.1-2.7-0.1-5.1,0.4-7.5
+			c0.7-3.6-0.5-5.8-3.6-7.6C158.1,175.2,156.3,173.5,154.2,171.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M135.8,71.6c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0.3-0.3,0.5-0.4,0.8c-6.4,13.6-12.8,27.2-19.1,40.8
+			c-2.2,4.8-2.8,9.9-1,15.1c0.1,0.4,0.4,0.8,0.7,1.5c0.7-0.9,1.3-1.4,1.7-2.1c0.9-1.7,1.9-3.5,2.6-5.3c4.9-11.9,8.5-24.3,12-36.7
+			C133.3,80.8,134.6,76.2,135.8,71.6z M107.9,120.8h4.9c0.2-1.1,0.4-2.2,0.6-3.4c0.8-4,2.9-7.5,4.6-11.2c6.4-13.7,12.8-27.4,19.2-41
+			c0.2-0.5,0.5-0.9,0.7-1.4c0.9-0.1,1.1,0.3,0.9,1.1c-5,18.4-9.6,37-16.5,54.9c-0.1,0.3-0.2,0.6-0.3,1.1c16.5,0.2,32.9,0.4,49.3,0.6
+			c-2,14.9-9.4,26.2-25.3,30c-4.7,1.1-9.5,1.1-14.2,0.3c-5.3-1-9.5-4.1-13.5-7.5c-6.6-5.8-10-13.2-10.4-22c0-0.3,0-0.6,0-0.9
+			C107.9,121.3,107.9,121.2,107.9,120.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M221.3,178.8c0.2,0,0.4-0.1,0.5-0.1c0-1.4,0.2-2.9,0-4.2c-0.8-4.5-1.6-9-2.7-13.4
+			c-3.1-12.5-7-24.7-11.1-36.8c-0.6-1.8-1.2-3.5-1.8-5.2c0.4,4.5,1.1,8.9,1.7,13.3c1.5,10.1,3,20.2,4.4,30.3c0.6,4.1,1.6,8.1,4,11.5
+			C217.8,176,219.3,177.7,221.3,178.8z M200.9,152h8.9c-0.4-2.9-0.8-5.5-1.2-8.2c-1.5-10.4-3-20.8-4.5-31.2
+			c-0.1-0.3,0.3-0.7,0.5-1.1c0.2,0,0.4,0.1,0.5,0.1c4.3,13.3,8.6,26.7,13,40.2c3.4,0,6.9,0,10.5,0c6.7-0.1,13.4-0.2,20.1-0.3
+			c5.1-0.1,10.2-0.1,15.2-0.2c1.1,0,1.5,0.4,1.8,1.4c3.3,12.5-1.7,25.9-12.4,33.4c-3.5,2.5-7.2,4.6-11.5,5.3
+			c-18.4,2.7-31.8-7.4-36.3-20.5c-1.4-4.1-2.1-8.5-3.2-12.7C201.9,156.2,201.4,154.2,200.9,152z"/>
+</vector>
diff --git a/res/drawable/icon_city.xml b/res/drawable/icon_city.xml
new file mode 100644
index 0000000..95c947d
--- /dev/null
+++ b/res/drawable/icon_city.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M103,289 L97.1,289 L97.1,214.1 L73.8,233 L73.8,289 L67.9,289 L67.9,230.1 L103,201.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M152.3,289 L146.4,289 L146.4,219.7 L132.2,231.9 L132.2,155.7 L108.2,177.2 L108.2,289 L102.3,289
+			L102.3,174.4 L138.1,142.4 L138.1,219 L152.3,206.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M206.9,289 L201,289 L201,117.8 L159,158 L159,289 L153.2,289 L153.2,155.4 L206.9,103.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M229.3,39.8 L180.8,85.9 L180.8,129.2 L186.7,129.2 L186.7,88.5 L223.4,53.6 L223.4,113.3 L229.3,113.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M223.5,112.8 L248.5,143.1 L248.5,289 L288.4,289 L288.4,105.8 L228.9,39.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M137.8,142.8 L156.4,166.1 L156.4,289 L149.5,289 L149.5,214.7 L135.1,225.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M105.2,289 L100,289 L100.8,207.2 L105.2,210.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M204.2,289 L206.8,104.8 L240.9,148.3 L240.9,289z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M25.3,280.4h317.3v11.6h-317.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M50.1,300.4h267.7v8.3h-267.7z"/>
+</vector>
diff --git a/res/drawable/icon_cry.xml b/res/drawable/icon_cry.xml
new file mode 100644
index 0000000..6a38179
--- /dev/null
+++ b/res/drawable/icon_cry.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+    android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M815.6,267.1c14.5,-2.7 27.8,-6.2 41.4,-7.5c26.9,-2.6 50.4,6.7 70.1,24.7c41.5,37.9 42.4,100.3 2.5,140.1c-1.2,1.2 -2.8,2.2 -4.3,3.4c7.1,6.3 13.8,11.7 19.8,17.7c17.4,17.4 33,36 41.6,59.5c30.6,83.6 -22.9,173.7 -110.6,186.3c-18.1,2.6 -36.2,1.7 -53.9,-3c-3.7,-1 -5.4,0 -7.5,2.9C757.3,770.7 681,822.3 584.5,840.4c-123.4,23.1 -232,-9.4 -324.8,-94.1c-8.2,-7.5 -16.6,-15 -25.7,-23.3c-6,1.8 -14.3,4.8 -22.9,7c-84.6,21.2 -172,-37.4 -184.3,-123.3c-6.8,-47.9 5.8,-89.8 38,-126.1c23,-25.9 49.5,-46.8 81,-61.2c2.8,-1.3 4,-3 4.6,-6c13.7,-74.1 46.7,-138.3 99.3,-192.2c51.4,-52.6 113.1,-87.8 185.1,-102.6c112.1,-23.2 214.3,0.2 305.6,69.8c28.8,21.9 53.2,48.1 74.1,77.6C815.1,266.6 815.8,267.3 815.6,267.1zM810.9,287.7c-1.4,-2.1 -2.6,-3.8 -3.8,-5.5c-14.9,-22.3 -31.9,-42.8 -51.7,-60.9c-85.9,-78.1 -186.5,-109.3 -301.2,-90.9c-84.3,13.6 -154.1,54.6 -209.7,119.3c-43.4,50.5 -69.9,109 -80.4,174.8c-0.5,2.9 -1.6,4.4 -4.3,5.5c-33.6,13.8 -61.4,35.3 -85.1,62.7c-28.2,32.6 -39.2,70.1 -32.4,112.5C54.6,682.2 130.2,733 206,715.2c11.7,-2.8 22.9,-7.5 34.9,-11.6c-0.5,-0.3 -0.2,-0.2 0.1,0c0.9,1 1.7,1.9 2.5,2.9c33.5,39.4 73.5,70.4 120.3,92.3c61,28.5 124.9,38.7 191.8,30.8c42.2,-5 82.1,-17.2 119.8,-36.8c54.9,-28.6 99.5,-68.8 133.6,-120.5c1.9,-2.9 3.5,-3.1 6.7,-2.2c10.3,2.6 20.7,5.8 31.2,6.7c51.9,4.1 100.1,-23.4 121.4,-70.9c19,-42.4 16.3,-84 -10.9,-122.8c-14.4,-20.5 -32.5,-37.2 -53.3,-51.1c-1.5,-1 -3,-2.2 -4.9,-3.6c3.4,-2.3 6.2,-4.2 8.9,-6.2c30.6,-21.3 42.9,-58.7 30.7,-93.8c-13.3,-38.3 -52.6,-57.4 -82.3,-53.7C840.6,276.7 825.7,280.8 810.9,287.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M797.6,325.8c1.6,-1.4 3,-2.7 4.5,-3.9c17.9,-15.6 38.9,-23.8 62.5,-24.1c26,-0.3 51,22.4 54.6,48.5c5.2,37.5 -23.2,68.5 -61,66.5c-9.4,-0.5 -18,-3.5 -26.1,-8.3c-1.5,-0.9 -3,-1.8 -5.2,-3.1c1.7,8.7 3.2,16.7 5,24.7c0.2,1 2.3,2 3.6,2.3c42.5,9.7 75.9,32.9 102.3,67.3c33.8,43.9 23.1,124.6 -44.8,151.1c-32.5,12.7 -63.8,8.6 -93,-10.5c-1.1,-0.7 -2.1,-1.4 -3.2,-2.1C736.6,734 650,793 532.8,800c-117.1,7 -210.1,-40.9 -282,-133c-0.9,0.7 -2.1,1.6 -3.3,2.6c-34.3,26.8 -72.2,33.5 -112.6,17.7c-39.8,-15.5 -63.1,-45.8 -69.7,-88c-5.9,-38.2 6.9,-70.5 33.2,-98.2c25.4,-26.8 55.1,-46.3 90.7,-56.3c2.6,-0.7 3.9,-1.8 4.2,-4.8c6,-48.7 21.6,-94.2 48.7,-135.2c52.6,-79.8 125.9,-129.4 220.5,-144.1c103.9,-16.1 195.2,12.8 272.6,84.1c24.2,22.3 43.9,48.3 60,77C795.9,323 796.6,324.2 797.6,325.8zM291,440.7c-2.6,-5.5 -6,-12 -8.6,-18.8c-0.6,-1.6 0.7,-5.1 2.1,-6c1.5,-1 4.6,-0.5 6.6,0.4c3,1.4 5.5,3.9 8.5,5.6c16.8,9.6 35.1,13.1 54.2,11.6c42.6,-3.4 79,-17.7 100.2,-58.2c0.8,-1.6 3.7,-3 5.4,-2.8c1.7,0.2 4.1,2.3 4.5,4c1,4.4 1.6,9 1.3,13.4c-1.1,16.8 -9.5,30.1 -21.5,41.1c-26.6,24.6 -58.7,34.1 -94.4,33.4c-2.1,0 -4.2,0 -6.2,0.4c-12.9,2.5 -23.3,9.4 -31.9,19c-20.4,22.6 -26.9,49.8 -24.1,79.2c2.4,24.7 0.4,48.4 -10.9,70.8c-1.6,3.1 -1.3,5.2 0.6,7.8c11.6,16.4 24.3,31.9 39.1,45.5c70.4,64.6 153.1,90.9 247.3,74.4c93.1,-16.3 161.2,-68.7 206.1,-151.6c1.5,-2.7 1.5,-4.8 0,-7.5c-10.6,-18.8 -13.6,-39.1 -12.1,-60.4c0.7,-9.8 1.1,-19.8 -0.1,-29.5c-2.8,-23.7 -13.4,-43.3 -33.7,-56.9c-2.7,-1.8 -5,-2 -8,-0.6c-4.8,2.2 -9.8,4.3 -14.9,5.6c-31.9,8.1 -62.3,3.3 -91.2,-11.4c-18.1,-9.2 -33.2,-21.8 -42.3,-40.5c-4.7,-9.7 -6.5,-20 -4.1,-30.6c0.5,-2.2 2.8,-4.8 4.8,-5.6c3.2,-1.2 5.1,1.4 6.4,4.4c4.7,10.7 12,19.5 20.8,27.1c20.9,17.8 45.5,27 72.5,29.4c24.8,2.2 48.4,-1.5 68.9,-17.1c1.5,-1.1 4.9,-1.1 6.5,-0.1c1.4,0.8 2.1,3.9 1.9,5.8c-0.3,3 -1.7,5.9 -2.4,8.4c17.7,-2.3 35.2,-4.6 53.6,-7c-2.7,-10.4 -5.4,-20.9 -8.2,-31.8c-10.9,3.3 -16.2,12.8 -25.2,17.9c3.3,-14.9 6.9,-29.6 11.1,-44.1c1.1,-3.7 1.1,-6.6 -0.6,-10.1c-14.7,-30.4 -33.8,-57.8 -58.3,-81.1c-72.5,-68.8 -158.7,-96.6 -256.4,-76.6c-112.6,23.1 -185.9,93 -220.9,202.6c-3.8,12 -5.8,24.6 -8.5,36.3C250.7,437.8 271.6,439.3 291,440.7zM311,462.4c-16.5,-4.5 -32.2,-7.7 -48.4,-9c-68.8,-5.2 -124.1,19.4 -166,74.4c-10.8,14.1 -15.9,30.2 -17.1,47.7c-4.2,61.7 46.5,110.3 107.9,103.7c47.4,-5.1 85.3,-47 85.2,-94.7c0,-14.8 -1.6,-29.7 -0.8,-44.5c1.5,-25.6 10.6,-48.5 28.3,-67.4C303.3,469.2 306.9,466.2 311,462.4zM738.7,447.4c26.3,22.7 35.2,51 34.8,83c-0.1,7.7 -1.4,15.5 -1.4,23.2c-0.1,63.8 67.4,104.8 123.8,75c49.6,-26.1 54.8,-85.5 33,-118.3c-16.7,-25.2 -39.1,-44.2 -66.7,-56.8c-29.7,-13.5 -60.9,-16.5 -92.9,-12C759.5,443 749.8,445.3 738.7,447.4zM786.4,374.9c0.6,0.2 0.9,0.3 1.2,0.3c18.8,-2.7 34.9,3.1 49.8,14.3c14.1,10.5 32.8,10.8 47.4,1.6c14.6,-9.2 22,-26.2 18.9,-43.6c-3.3,-18.9 -22.8,-35.3 -40.9,-34.4C826.8,315 796.1,339.7 786.4,374.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M401.6,648.3c1.3,-4.1 3.1,-12.6 6.7,-20.2c18.4,-38.2 44.9,-69.7 80.2,-93.4c13.6,-9.1 28.5,-15.6 45.5,-13c13.4,2 25.2,8.2 35.9,16.1c33.6,24.7 59.6,55.8 76.6,94c3.1,7.1 4.8,15.1 5.4,22.9c0.8,9.6 -5.6,14.7 -14.9,12.2c-7.3,-1.9 -14.3,-4.9 -21.2,-8.1c-18.9,-8.8 -37.4,-18.3 -56.4,-26.7c-21.5,-9.5 -43.5,-9.4 -65,0c-19.8,8.7 -39.1,18.4 -58.7,27.6c-5.5,2.6 -11.2,5 -17.1,6.6C407.2,669.5 401.5,664.7 401.6,648.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M480.7,305.7c-9.2,-1.8 -16.4,-3.7 -23.8,-4.6c-44,-5.1 -80.7,9.1 -110.3,41.8c-1.3,1.4 -2.4,3 -3.7,4.5c-4.1,4.5 -10,5.1 -14.2,1.5c-4.1,-3.5 -4.9,-9.5 -0.9,-13.9c6.7,-7.4 13.2,-15.2 21,-21.4c39.2,-31.6 83.4,-40.6 132,-27.7c8,2.1 11.4,9.8 6.7,15.5C485.4,303.7 482,304.8 480.7,305.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M568.6,279.9c51.8,0.6 90.4,18.1 120.2,54.4c3.5,4.3 3.9,8.7 1.3,12.5c-2.7,3.9 -6.6,5.4 -11,3.9c-2.1,-0.7 -4.2,-2.4 -5.7,-4.2c-24.5,-29.5 -55.9,-45.1 -94.2,-46.6c-12.8,-0.5 -25.4,1.4 -37.8,5c-8.3,2.4 -14.8,-3 -13.5,-11c0.8,-4.6 3.8,-7.1 8.1,-8C548.4,283.5 561,281.3 568.6,279.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M122.3,639.5c-9,-18.7 -14.4,-37.8 -14.5,-58.1c-0.1,-15.3 3.3,-29.8 11.6,-42.9c6.2,-9.8 14.3,-17.7 25,-24.2c-18.4,40 -19.1,77.2 12.4,111.1C145.4,630 134.2,634.6 122.3,639.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M903.8,603.7c-10.4,-4.2 -20.2,-8.2 -30.5,-12.5c12.6,-13.2 20.5,-28.3 22.1,-46.5c1.5,-17.9 -3,-34.5 -10.6,-50.5c0.4,-0.4 0.7,-0.7 1.1,-1.1c5.3,4.9 11.1,9.4 15.7,14.9c13.9,16.4 16.9,35.8 14.4,56.5C914.3,578 910.3,590.9 903.8,603.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M898.2,347.4c-4.4,3.4 -8.9,6.8 -13.8,10.5c-6.3,-20.6 -21.2,-29.7 -41.6,-32C860.8,314.5 885.7,325.8 898.2,347.4z"/>
+</vector>
diff --git a/res/drawable/icon_cry_color.xml b/res/drawable/icon_cry_color.xml
new file mode 100644
index 0000000..3079370
--- /dev/null
+++ b/res/drawable/icon_cry_color.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FFFFFF" android:pathData="M285,104.6c-2.8,-1.3 -5.9,-2.2 -9.1,-2.6c-14.8,-1.8 -28.7,7.6 -35.6,22.3c4.3,-20.7 21.1,-35.2 39.2,-33L285,104.6z"/>
+    <path android:fillColor="#FFE448"
+        android:pathData="M181.7,179.2m-112,0a112,112 0,1 1,224 0a112,112 0,1 1,-224 0"
+        android:strokeColor="#FFFFFF" android:strokeWidth="1.3498"/>
+    <path android:fillColor="#654E2B" android:pathData="M135.5,162.2c-12.4,3.1 -24.4,0.9 -31.3,-4.8c-1.3,-1.1 -3.4,0.2 -3,1.9c0,0 0,0 0,0.1c2.9,11.8 19.4,17.8 36.9,13.4s29.2,-17.4 26.3,-29.1c0,0 0,0 0,-0.1c-0.4,-1.7 -2.8,-1.9 -3.5,-0.2C157.5,151.6 148,159.1 135.5,162.2z"/>
+    <path android:fillColor="#654E2B" android:pathData="M227.8,162.2c12.4,3.1 24.4,0.9 31.3,-4.8c1.3,-1.1 3.4,0.2 3,1.9c0,0 0,0 0,0.1c-2.9,11.8 -19.4,17.8 -36.9,13.4s-29.2,-17.4 -26.3,-29.1c0,0 0,0 0,-0.1c0.4,-1.7 2.8,-1.9 3.5,-0.2C205.8,151.6 215.3,159.1 227.8,162.2z"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M208,162.8"
+        android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M114.8,162.8"
+        android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M161.4,209.3"
+        android:strokeColor="#231F20" android:strokeWidth="1.3498"/>
+    <path android:fillColor="#6BB4EC" android:pathData="M118,172.8c-61.2,-21 -86.2,26.2 -86.2,26.2l-0.6,1.2c-5,11.3 -4.1,25.5 3.6,36.3c11.7,16.3 34.4,20.1 50.7,8.4c10.3,-7.3 15.6,-19 15.2,-30.8l0,-2c0,0 -5.2,-26.5 16.1,-38.9L118,172.8z"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M57.8,230.2c-17.1,-17 -4.3,-38.7 -4.3,-38.7l0,0c-23.2,14.7 -7.8,43.5 -7.8,43.5l11.2,-4.6L57.8,230.2z"/>
+    <path android:fillColor="#6BB4EC" android:pathData="M253.5,167.7c54,-18.6 76.1,23.2 76.1,23.2l0.5,1.1c4.4,10 3.6,22.5 -3.2,32c-10.3,14.4 -30.3,17.7 -44.7,7.4c-9.1,-6.5 -13.7,-16.8 -13.4,-27.1l0,-1.8c0,0 4.6,-23.4 -14.2,-34.4L253.5,167.7z"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M306.7,218.3c15.1,-15 3.8,-34.2 3.8,-34.2l0,0c20.5,13 6.9,38.4 6.9,38.4l-9.9,-4.1L306.7,218.3z"/>
+    <path android:fillColor="#6BB4EC" android:pathData="M272.3,148.1c6.2,-30.2 31.7,-29.1 31.7,-29.1l0.7,0.1c5.9,0.7 11.5,4.5 14,10.3c3.9,8.8 -0.1,19 -8.9,22.9c-5.5,2.4 -11.6,1.8 -16.3,-1.2l-0.8,-0.5c0,0 -9.6,-8.6 -19.9,-2.9L272.3,148.1z"/>
+    <path android:fillColor="#FFFFFF" android:pathData="M310.5,137.2c-2.8,-11.2 -14.9,-11.2 -14.9,-11.2l0,0c11.7,-6 19.8,7.4 19.8,7.4l-4.6,3.5L310.5,137.2z"/>
+    <path android:fillColor="#654E2B" android:pathData="M117.8,134.3L117.8,134.3c-1.6,-1.1 -2,-3.3 -0.8,-4.9c9.4,-12.1 23.9,-19.2 39.3,-19.2c5,0 9.9,0.7 14.6,2.2c1.9,0.6 2.8,2.6 2.1,4.4l0,0c-0.6,1.7 -2.4,2.5 -4.1,2c-4,-1.2 -8.3,-1.8 -12.5,-1.8c-13.3,0 -25.8,6.1 -34,16.5C121.2,134.9 119.2,135.3 117.8,134.3z"/>
+    <path android:fillColor="#654E2B" android:pathData="M242.1,134.3L242.1,134.3c1.6,-1.1 2,-3.3 0.8,-4.9c-9.4,-12.1 -23.9,-19.2 -39.3,-19.2c-5,0 -9.9,0.7 -14.6,2.2c-1.9,0.6 -2.8,2.6 -2.1,4.4l0,0c0.6,1.7 2.4,2.5 4.1,2c4,-1.2 8.3,-1.8 12.5,-1.8c13.3,0 25.8,6.1 34,16.5C238.6,134.9 240.6,135.3 242.1,134.3z"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M342.5,186.5l-0.1,-0.2l-0.7,-1.5l-0.1,-0.2c-0.4,-0.8 -7.1,-13 -21.2,-22.8c5.1,-3.5 9,-8.4 11.3,-14.3c3,-7.7 2.8,-16.1 -0.5,-23.6c-4.4,-9.9 -13.9,-16.9 -24.7,-18.2l-0.2,0l-0.9,-0.1l-0.5,0c0,0 -0.4,0 -1,0c-1.7,0 -9.2,0.2 -17.7,4c-22.5,-33.6 -60.9,-55.8 -104.3,-55.8C119,53.6 67,99.8 57.6,159.8c-25.6,10.6 -37.1,31.7 -37.8,32.9l-0.1,0.2l-0.8,1.7l-0.1,0.2c-7.1,16.3 -5.2,35.3 5,49.6c9.3,13 24.5,20.8 40.5,20.8c0,0 0,0 0,0c7.6,0 14.9,-1.7 21.6,-5c23,27.1 57.4,44.4 95.7,44.4c43.6,0 82.1,-22.4 104.6,-56.3c4.7,1.6 9.6,2.4 14.6,2.4c14.7,0 28.5,-7.1 37.1,-19C347.3,218.8 349,201.4 342.5,186.5z"
+        android:strokeColor="#231F20" android:strokeWidth="5.3992"/>
+    <path android:fillColor="#654E2B" android:pathData="M228.1,244.2c-6,3.6 -29.7,-14.2 -41.7,-14.2c-8.9,0 -16.6,3.2 -25.5,7.7c-5.4,2.8 -13.1,8.5 -16.2,6.5c-12.4,-8 22.7,-50.9 41.7,-50.3C205.3,194.6 240.1,236.9 228.1,244.2z"/>
+</vector>
diff --git a/res/drawable/icon_fork_and_knife.xml b/res/drawable/icon_fork_and_knife.xml
new file mode 100644
index 0000000..7690c80
--- /dev/null
+++ b/res/drawable/icon_fork_and_knife.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="28dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="28dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M63.1,173.7c15.9,-0.3 31.7,-0.5 47.4,-0.8c-17.5,-17.8 -33.7,-36.8 -49.8,-55c12.7,-12.7 25.4,-25.3 38.1,-38.1c1.4,1.2 3.2,2.7 4.9,4.3c14,12.6 28.1,25.2 42.1,37.8c2.3,2.1 4.5,4.3 6.7,6.5c7.9,8.4 9.5,18.1 5.8,28.8c-0.4,1 -0.2,1.5 0.6,2.3c4.6,4.2 9.1,8.4 13.6,12.6c1,0.9 3.3,1 4.3,0.1c5.5,-5.1 11,-10.3 16.5,-15.4c0.3,-0.2 0.5,-0.8 0.4,-1.1c-4,-12.7 -1.5,-24.8 4.7,-36.1c8.3,-15.2 20.5,-25.9 37.1,-31.2c8.9,-2.9 17.9,-3.3 26.8,0.1c11.5,4.4 18.1,13.1 19.8,25.1c1.8,12.3 -1.8,23.5 -8.4,33.8c-7,11 -16.4,19.3 -28.2,24.8c-0.2,0.1 -0.4,0.2 -0.6,0.6c16.9,0.2 33.8,0.5 50.9,0.7c1.1,6.8 2.1,13.4 3.2,20.2c12.7,0.2 25.3,0.5 38,0.7c-0.1,0.3 -0.3,0.7 -0.5,1.2c-4.2,8.1 -8.3,16.3 -12.5,24.4c-0.5,0.9 -0.2,1.5 0.2,2.2c7.3,11.3 14.7,22.6 22,33.8c0.2,0.3 0.4,0.7 0.9,1.4c-20.9,-0.3 -41.6,-0.6 -62.4,-1c-0.2,-1.6 -0.5,-3.4 -0.7,-5.1c-0.6,-4.6 -1.1,-9.2 -1.6,-13.8c-0.1,-0.9 -0.5,-1.2 -1.3,-1.2c-10.5,0 -21,0 -31.4,-0.1c-2.6,0 -5.1,0 -7.7,0c0,0.1 -0.1,0.3 -0.1,0.4c1.6,1.5 3.1,3 4.7,4.4c3.3,2.9 5.9,6.2 6.8,10.6c1.7,7.6 -1.8,15.3 -8.7,19.1c-6.6,3.6 -15.2,2.6 -20.5,-2.9c-7.4,-7.7 -14.6,-15.6 -21.8,-23.4c-2.2,-2.4 -4.4,-4.8 -6.7,-7.1c-0.4,-0.4 -1,-0.7 -1.6,-0.7c-12.6,0 -25.2,0 -37.7,0c-1,0 -1.7,0.2 -2.4,1c-8.3,9 -16.7,18 -25.1,26.9c-6.6,7.1 -17.9,7.5 -24.7,0.8c-7.2,-7.1 -7.3,-18.1 -0.1,-25.1c1.1,-1.1 2.2,-2.1 3.4,-3.3c-0.4,-0.1 -0.7,-0.2 -1,-0.2c-9.8,0 -19.6,0.1 -29.4,0.1c-0.9,0 -1.3,0.3 -1.4,1.3c-0.6,5.7 -1.4,11.3 -2.1,17c-0.1,0.5 -0.1,1 -0.2,1.4c-20.7,0.3 -41.3,0.6 -62.3,1c0.5,-0.8 0.8,-1.2 1,-1.7c7.3,-11.2 14.6,-22.4 21.9,-33.6c0.6,-0.9 0.5,-1.5 0.1,-2.4c-4.2,-8.2 -8.4,-16.4 -12.6,-24.6c-0.1,-0.2 -0.2,-0.5 -0.3,-0.6c13.2,-0.3 26.3,-0.5 39.6,-0.8C61.5,186.9 62.3,180.4 63.1,173.7zM187.6,172.7c5.4,0 10.5,0 15.5,0c0.4,0 0.9,-0.4 1.2,-0.7c1.8,-1.9 3.6,-3.8 5.4,-5.8c0.6,-0.7 1.1,-0.9 1.9,-0.4c0.8,0.5 1.7,0.9 2.6,1.3c7.2,2.8 14.4,2.6 21.6,0.3c16.5,-5.3 28.2,-16.2 35.3,-31.9c3.1,-6.8 4.5,-14 3.2,-21.5c-1.6,-8.9 -6.5,-15.3 -15.1,-18.5c-6.5,-2.4 -13.2,-2.2 -19.7,-0.3c-17.1,5.1 -29.1,16.1 -36.4,32.2c-3,6.6 -4.2,13.7 -3.2,21c0.5,3.4 1.7,6.6 3.4,9.6C198.1,162.9 193,167.7 187.6,172.7zM86.9,102.3c13.3,13 26.5,26 39.5,38.8c-1.4,1.5 -2.8,2.9 -4.3,4.4c-13,-13 -26.1,-26.1 -39.2,-39.2c-1.2,1.2 -2.4,2.4 -3.6,3.7c12.9,13.2 25.9,26.4 38.8,39.5c-1.4,1.4 -2.7,2.8 -4.1,4.2c-13,-13.2 -26,-26.5 -39,-39.7c-1.4,1.3 -2.6,2.5 -3.9,3.8c0.3,0.4 0.5,0.7 0.8,1c5.5,6.2 10.9,12.5 16.5,18.6c8.5,9.3 17,18.6 25.7,27.8c4.9,5.3 11.1,7.5 18.2,5.8c3.1,-0.7 6,-2.2 9.2,-3.4c1,1.1 2.4,2.5 3.7,4c0.7,0.8 1.5,1.2 2.6,1.2c4.1,-0.1 8.3,0 12.4,0c0.4,0 0.8,0 1.6,-0.1c-4.6,-4.3 -9,-8.4 -13.4,-12.5c0.8,-1.7 1.7,-3.2 2.4,-4.8c3.2,-7.8 2.4,-15 -3.4,-21.4c-1.5,-1.6 -3.1,-3.2 -4.7,-4.7c-10.8,-9.9 -21.7,-19.7 -32.6,-29.5c-3.7,-3.3 -7.4,-6.5 -11.1,-9.7c-1.3,1.3 -2.6,2.5 -4,3.8c13.3,13 26.5,26.1 39.7,39c-1.4,1.5 -2.7,2.8 -4.1,4.2c-13.2,-12.9 -26.4,-25.9 -39.5,-38.8C89.6,99.7 88.3,101 86.9,102.3zM288,182.3c-72.4,-0.8 -144.6,-0.8 -216.9,0.2c-1.7,15.2 -3.4,30.3 -5.1,45.2c76.5,-0.2 152.7,-0.3 229,-0.5C292.7,212.2 290.3,197.4 288,182.3zM55.9,236.9c1.3,-11.5 2.5,-22.9 3.8,-34.4c-8.1,0.3 -16,0.5 -24,0.8c0.4,0.7 0.6,1.3 0.9,1.8c2.6,4.9 5.2,9.8 7.8,14.7c0.5,1 0.5,1.6 -0.1,2.5c-5.2,8.1 -10.4,16.3 -15.6,24.5c-0.2,0.4 -0.4,0.7 -0.7,1.2c12.5,-0.3 24.9,-0.5 37.3,-0.8c0.4,-3.4 0.8,-6.9 1.3,-10.4C63,236.9 59.5,236.9 55.9,236.9zM330,248.1c-0.4,-0.7 -0.7,-1.1 -1,-1.6c-5,-7.9 -10,-15.8 -15.1,-23.7c-0.8,-1.2 -0.9,-2.1 -0.1,-3.4c2.8,-5 5.4,-10.1 8.1,-15.2c0.2,-0.3 0.2,-0.6 0.4,-1c-7.4,-0.2 -14.6,-0.5 -21.9,-0.7c1.8,11.3 3.5,22.5 5.3,33.8c-4.8,0 -9.5,0 -14.3,0c0.5,3.8 0.9,7.3 1.3,10.9C305.1,247.6 317.4,247.9 330,248.1zM205.9,236.4c0,0.1 -0.1,0.2 -0.1,0.3c2.1,2.3 4.3,4.6 6.4,6.8c5.8,6.2 11.5,12.4 17.3,18.6c1.9,2.1 4.4,3.1 7.2,2.9c4.2,-0.3 7.3,-2.4 8.7,-6.5c1.4,-4 0.4,-7.6 -2.7,-10.5c-3.9,-3.6 -7.7,-7.3 -11.7,-10.8c-0.6,-0.5 -1.5,-0.9 -2.3,-0.9c-6.6,0 -13.1,0 -19.7,0C208,236.4 206.9,236.4 205.9,236.4zM144.1,236.6c-0.3,-0.1 -0.4,-0.1 -0.6,-0.1c-7.9,0 -15.8,0 -23.7,0.1c-0.5,0 -1.1,0.2 -1.4,0.6c-3.1,2.8 -6.2,5.6 -9.2,8.6c-3.9,3.8 -3.9,10 0,13.8s10.2,3.6 13.9,-0.4c5.1,-5.5 10.2,-11 15.3,-16.4C140.4,240.6 142.2,238.7 144.1,236.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M219.2,157.5c22.3,0.5 43.5,-21.5 43.1,-44c1.3,2.4 1.8,4.6 2.1,7c1.1,10.7 -3,19.6 -10,27.4c-5.4,6 -12.1,10.1 -20.1,11.6c-4.6,0.9 -9.2,0.7 -13.7,-1.2c-0.3,-0.1 -0.6,-0.2 -0.9,-0.4C219.6,157.8 219.5,157.7 219.2,157.5z"/>
+</vector>
diff --git a/res/drawable/icon_happy.xml b/res/drawable/icon_happy.xml
new file mode 100644
index 0000000..ed5327f
--- /dev/null
+++ b/res/drawable/icon_happy.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="1008"
+    android:viewportHeight="1008">
+
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M491.1,869.9c-101.8-1.7-190.2-36.8-264.2-107.5c-22.9-21.9-42.3-46.5-59.1-73.3c-1.7-2.7-4.6-5.3-7.5-6.6
+c-42.7-19.2-75.5-48.7-91.8-93.1c-22.2-60.2-8.9-114.2,33.2-161.6c3.3-3.7,6.7-7.5,10.7-10.5c5.8-4.2,8.1-9.8,9.7-16.6
+c16.3-68.4,49.5-127.5,98.7-177.6c53.9-54.9,118.5-91,194.1-105.4c127.4-24.2,240,7.3,336.1,94.6c42.9,38.9,73.8,86.3,95,140.2
+c1,2.4,3,4.7,5.2,6.3c35,26.1,58,59.8,65,103.4c7,44.2-3.9,84.1-31.4,119c-9.2,11.7-20.9,21.3-31.4,32c-2,2.1-4.1,4.4-5.1,7
+c-42.6,109.6-118.5,185.6-228.7,226.9c-38.3,14.4-78.3,21.3-119.2,22.1C497.3,869.4,494.3,869.7,491.1,869.9z
+M490.9,853.6
+c3.2,0,6.3,0.1,9.5,0c38.7-1,76.6-7.4,112.9-21C721,792.4,794.6,717.8,835,610.2c0.9-2.5,2.8-4.7,4.7-6.6
+c10.4-10.3,22.2-19.4,31.3-30.7c25.9-32.1,36.2-68.9,29.1-109.9c-6.9-39.9-28.8-70.2-61.4-93.5c-2.7-2-5.3-5.1-6.5-8.2
+c-17.1-44.7-41.1-85.4-74.5-119.6c-97-99.5-214.4-135.9-350.1-106.1c-137.2,30.1-244.3,142-272.9,280c-0.5,2.3-2.3,4.6-4,6.5
+c-8.8,9.3-19,17.5-26.6,27.6C68.9,497,63.4,547.5,90.9,600.1c17.3,33.1,45.2,54.9,79.4,69c3.6,1.5,6.3,3.4,8.6,6.9
+C251,791.2,355.8,849.1,490.9,853.6z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M514.3,723.5c-67.4-1-118.8-23.7-162.2-64.8c-37-35.1-61.5-77.9-75.4-126.8c-0.9-3.2-0.9-7.4,0.4-10.4
+c2-4.7,7.7-5.1,12.9-1.7c20.2,13.1,41.1,24.7,63.6,33.3c117.2,44.6,226.7,29.4,328.2-43.7c14.4-10.4,27.1-23,40.5-34.9
+c3.8-3.3,7.5-4.8,12.2-2.7c4.7,2.1,5.8,6.1,5.4,10.8c-4.1,48.5-18.1,93.7-45.1,134.4c-34.5,52.1-81,87.8-142.9,101.3
+C537.3,721.5,522.2,722.4,514.3,723.5z
+M498.3,691.2c35,0,59.6-5.2,82.9-16c47.7-22.1,80.7-58.8,103.2-105.6
+c2.8-5.8,2.3-10-1.3-13.2c-3.6-3.2-7.9-3.2-13.3-0.2c-10.9,6-21.7,12.3-32.9,17.7C586.7,598,533.7,610,478.1,609.9
+c-41.8,0-82.4-7.3-121.8-21.3c-4.4-1.6-8.6-1.8-11.7,2.4c-3,4.1-2,8.2,1.1,11.9c9.1,10.6,17.5,21.9,27.5,31.6
+C410.7,670.4,455.1,690.6,498.3,691.2z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M164.1,436.6c16.1-121.6,120.1-256,286-276.3c177.5-21.7,316.7,95.4,356.9,227c-1.3-0.5-2.3-0.9-3.3-1.2
+c-11.9-4.1-23.8-8.5-35.8-12.3c-3.3-1-5.2-2.4-6.7-5.6c-40.4-85.6-106-141.4-197.5-165.4c-132.7-34.8-274.8,30.3-336.3,153
+c-9.6,19.3-17.4,39.2-22.8,60.1c-0.4,1.6-1.8,3.6-3.3,4.3c-11.9,5.6-23.9,10.9-35.8,16.2C165.1,436.5,164.6,436.5,164.1,436.6z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M198.9,646.1c9.6,1.5,18.8,3,28,4.3c2.5,0.4,5,0.9,7.5,0.5c6.6-0.9,10.2,1.9,14,7.3
+c48.1,67.8,113,110.3,195.1,123.3c94,14.9,177.1-10.5,248-74.2c30.9-27.8,54.3-61.2,70.9-99.3c1.2-2.8,2.8-4.2,5.9-5.3
+c13.6-4.7,27-10,39.7-14.8c-27.1,98.9-123.6,211.4-273,230.8C374.4,839.7,249.1,745.2,198.9,646.1z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M403.7,472.1c-11.4-10.2-18.2-22.9-21-37.6c-4.3-22-0.7-42.5,13-60.5c21.8-28.5,59.3-28.1,80.7,0.6
+c18.6,24.8,18.8,62.4,0.5,87.4c-0.9,1.2-1.9,2.3-3.4,4.1c-0.2-4.5-0.2-8.4-0.6-12.2c-1-10.3-5-19.3-12.3-26.7
+c-13.5-13.6-33.2-13.1-46,1.1c-9.5,10.5-12.7,23.1-11.3,37c0.2,1.8,0.5,3.6,0.7,5.4C404.3,471.2,404,471.5,403.7,472.1z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M612.5,453.7c-0.6-5.9-0.6-11.4-1.7-16.7c-3.4-17.3-16.1-29.9-31.3-31.3c-10.8-1-19.6,3.3-26.5,11.2
+c-9.7,11.1-12.6,24.3-10.6,38.7c0.1,1,0.4,2,0.5,3c0,0.3-0.1,0.6-0.4,1.8c-2.7-2.8-5.2-5.1-7.4-7.8c-21.1-25.6-20.6-67.8,1-93
+c21.7-25.4,56.5-24.9,77.4,1.1c20.3,25.2,20.9,64.5,1.3,90.3C614.3,451.9,613.5,452.7,612.5,453.7z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M449.2,281.7c0,8.4-6,14.7-14.5,15.3c-38.7,2.9-65.6,22.2-80.1,58.3c-3.8,9.4-12.1,13.5-20.7,10.2
+c-8.3-3.1-11.7-11.9-8.4-21.1c16-44.7,58.8-76.4,106-78.4C442,265.6,449.2,271.9,449.2,281.7z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M556.6,254.6c43.5,1.6,76.7,18.7,100.5,53c5.9,8.5,4.6,17.7-2.9,22.9c-7.6,5.3-16.7,2.9-22.9-5.5
+c-22.4-30.8-52.4-43.5-90.1-37.4c-9.7,1.6-17.9-3.5-19.3-12.1c-1.5-9.4,3.9-17,13.8-18.5C543.3,255.9,551,255.3,556.6,254.6z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M719.2,400c44.2,0.7,87.2,30.1,103.7,71.1c2.3,5.8,1,10.2-3.8,12.1c-4.5,1.8-8.4-0.3-11-5.7
+c-18.3-39.4-49.1-59.9-92.6-61.5c-5.8-0.2-9.4-3.2-9.4-8.1c0.1-4.8,3.7-7.8,9.5-7.9C716.9,400,718,400,719.2,400z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M299,450.5c0.1,4.2-2.7,7.3-7.5,7.6c-13.8,1-27,4-39.3,10.3c-22.2,11.3-37.7,28.6-46.9,51.6
+c-0.2,0.6-0.4,1.3-0.7,1.9c-2,4.9-5.9,7-10.1,5.4c-4.3-1.6-6.5-5.8-4.2-10.7c4.2-9,8.2-18.4,13.9-26.4
+c20.7-29.3,49.5-44.6,85.1-47.2C295.2,442.6,298.9,445.7,299,450.5z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/icon_happy_color.xml b/res/drawable/icon_happy_color.xml
new file mode 100644
index 0000000..b03fd49
--- /dev/null
+++ b/res/drawable/icon_happy_color.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="360"
+    android:viewportHeight="360">
+
+    <path
+        android:fillColor="#FFE448"
+        android:strokeColor="#FFFFFF"
+        android:strokeWidth="1.5402"
+        android:strokeMiterLimit="10"
+        android:pathData="M 181.4 51.1 C 251.981991028 51.1 309.2 108.318008972 309.2 178.9 C 309.2 249.481991028 251.981991028 306.7 181.4 306.7 C 110.818008972 306.7 53.6 249.481991028 53.6 178.9 C 53.6 108.318008972 110.818008972 51.1 181.4 51.1 Z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:strokeColor="#231F20"
+        android:strokeWidth="1.7331"
+        android:strokeMiterLimit="10"
+        android:pathData="M208.8,142.3" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:strokeColor="#231F20"
+        android:strokeWidth="1.5402"
+        android:strokeMiterLimit="10"
+        android:pathData="M103.9,166.4" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:strokeColor="#231F20"
+        android:strokeWidth="1.5402"
+        android:strokeMiterLimit="10"
+        android:pathData="M161.1,215.1" />
+    <path
+        android:fillColor="#FFE448"
+        android:pathData="M 86.8 149.6 C 116.568148016 149.6 140.7 170.060586933 140.7 195.3 C 140.7 220.539413067 116.568148016 241 86.8 241 C 57.0318519841 241 32.9 220.539413067 32.9 195.3 C 32.9 170.060586933 57.0318519841 149.6 86.8 149.6 Z" />
+    <path
+        android:fillColor="#FFE448"
+        android:pathData="M 273.4 133 C 303.168148016 133 327.3 153.460586933 327.3 178.7 C 327.3 203.939413067 303.168148016 224.4 273.4 224.4 C 243.631851984 224.4 219.5 203.939413067 219.5 178.7 C 219.5 153.460586933 243.631851984 133 273.4 133 Z" />
+    <path
+        android:fillColor="#654E2B"
+        android:pathData="M103.3,190.2c-2.5-1.7-5.7,0.7-5,3.6c12.6,46.1,51.9,78.2,95.7,74.7c45-3.6,79.4-43.7,82.9-93
+c0.2-3.4-3.9-5.2-6.3-2.8c-22.4,22.5-51.3,37.1-83.7,39.8C156.8,214.9,127.9,206.5,103.3,190.2z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M193.1,256.3c-26.7,2.1-52-11.5-68.2-34.5c-1.9-2.6,0.8-6.1,3.8-5c19,6.9,39,9.6,59.4,8
+c22.2-1.8,43.6-8.9,62.7-20.6c3.1-1.9,6.8,1.3,5.3,4.6C243.9,235.3,220.6,254,193.1,256.3z" />
+    <path
+        android:fillColor="#654E2B"
+        android:pathData="M181,151.6c0-14-9.4-25.3-21-25.3s-21,11.3-21,25.3c0,8.6,3.6,16.2,9.1,20.8c-0.4-1.6-0.6-3.2-0.6-5
+c0-9,6.1-16.3,13.6-16.3c7.5,0,13.6,7.3,13.6,16.3c0,0.9-0.1,1.8-0.2,2.6C178.4,165.4,181,158.9,181,151.6z" />
+    <path
+        android:fillColor="#654E2B"
+        android:pathData="M67.3,193.5L67.3,193.5c-1.6-0.4-2.5-2.1-2-3.7c4.3-12.4,14.1-22.2,26.6-26.5c4-1.4,8.2-2.1,12.4-2.3
+c1.7-0.1,3,1.3,3,3l0,0c-0.1,1.5-1.3,2.7-2.8,2.8c-3.6,0.1-7.2,0.8-10.7,2c-10.8,3.7-19.2,12.1-23,22.8
+C70.3,193.1,68.8,193.9,67.3,193.5z" />
+    <path
+        android:fillColor="#654E2B"
+        android:pathData="M307.4,176.5L307.4,176.5c1.7-0.5,2.5-2.4,1.9-4c-5.1-12.7-15.8-22.4-29.1-26.3c-4.3-1.2-8.7-1.8-13.1-1.8
+c-1.7,0-3.1,1.6-2.9,3.3l0,0c0.1,1.6,1.5,2.8,3.1,2.8c3.8,0,7.6,0.5,11.3,1.5c11.5,3.3,20.7,11.7,25.1,22.7
+C304.2,176.2,305.8,177,307.4,176.5z" />
+    <path
+        android:fillColor="#654E2B"
+        android:pathData="M234.4,147c0-14-9.4-25.3-21-25.3c-11.6,0-21,11.3-21,25.3c0,8.6,3.6,16.2,9.1,20.8c-0.4-1.6-0.6-3.2-0.6-5
+c0-9,6.1-16.3,13.6-16.3c7.5,0,13.6,7.3,13.6,16.3c0,0.9-0.1,1.8-0.2,2.6C231.8,160.8,234.4,154.3,234.4,147z" />
+    <path
+        android:fillColor="#654E2B"
+        android:strokeColor="#654E2B"
+        android:strokeWidth="6.1608"
+        android:strokeMiterLimit="10"
+        android:pathData="M122.1,128.4L122.1,128.4
+c-1.6-0.4-2.5-2.1-2-3.7c4.3-12.4,14.1-22.2,26.6-26.5c4-1.4,8.2-2.1,12.4-2.3c1.7-0.1,3,1.3,3,3l0,0c-0.1,1.5-1.3,2.7-2.8,2.8
+c-3.6,0.1-7.2,0.8-10.7,2c-10.8,3.7-19.2,12.1-23,22.8C125.1,127.9,123.6,128.8,122.1,128.4z" />
+    <path
+        android:strokeColor="#231F20"
+        android:strokeWidth="6.1608"
+        android:strokeMiterLimit="10"
+        android:pathData="M342.5,173.2c-1.5-18.1-11.5-33.6-26.6-43.6
+c-7.8-21.2-20.5-40.5-37.5-56.1c-26.5-24.4-60.9-37.8-96.8-37.8c-3.9,0-7.8,0.2-11.6,0.5c-38.1,3.1-72.8,20.8-97.6,49.9
+c-15.9,18.7-26.6,40.7-31.3,64.2c-2,1.6-3.8,3.2-5.6,5c-12.7,12.7-19,28.9-17.6,45.6c1.9,23,17.7,42,40.1,50.6
+c7.1,12.1,16,23.3,26.6,33c26.5,24.4,60.9,37.8,96.8,37.8c3.9,0,7.8-0.2,11.6-0.5c58.4-4.7,105.8-44,123.9-96.1
+c2.9-2.1,5.6-4.4,8.1-6.9C337.5,206.1,343.8,189.9,342.5,173.2z" />
+    <path
+        android:fillColor="#654E2B"
+        android:strokeColor="#654E2B"
+        android:strokeWidth="6.1608"
+        android:strokeMiterLimit="10"
+        android:pathData="M196.3,96.1L196.3,96.1
+c-0.5-1.6,0.5-3.3,2.2-3.6c12.9-2.7,26.3,0.7,36.4,9.2c3.3,2.8,6,5.9,8.3,9.5c0.9,1.4,0.4,3.3-1.1,4.1l0,0c-1.3,0.7-3,0.3-3.8-1
+c-2-3-4.4-5.8-7.2-8.2c-8.7-7.4-20.3-10.3-31.4-8C198.2,98.5,196.7,97.6,196.3,96.1z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/icon_hello.xml b/res/drawable/icon_hello.xml
new file mode 100644
index 0000000..1181ec2
--- /dev/null
+++ b/res/drawable/icon_hello.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="72.0"
+    android:viewportWidth="72.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M27.6,44.6c0,0 -0.1,0.1 -0.1,0.1c-0.4,1.1 -1.2,1.8 -2.4,1.9c-1.2,0.2 -2.4,-0.1 -3.5,-0.6c-0.1,0 -0.2,-0.1 -0.3,-0.1c-1.4,-1.2 -2.3,-2.6 -2.2,-4.6c0,-0.2 0.1,-0.5 0.2,-0.7c0.1,-0.2 0.1,-0.5 0.1,-0.7c-0.1,-0.9 -0.2,-1.7 -0.3,-2.6c-0.3,0.1 -0.5,0.2 -0.8,0.3c0,0 -0.1,0.1 -0.1,0.2c0.2,1.6 0.3,3.1 0.5,4.7c0.2,1.4 0.5,2.8 0.7,4.2c0.3,1.6 -0.8,3 -2.5,3.2c-1.2,0.1 -2.4,-0.1 -3.5,-0.6c-0.4,-0.2 -0.8,-0.6 -1.2,-0.9c-0.1,0 -0.1,-0.2 -0.1,-0.2c-0.5,-2.3 -0.8,-4.6 -1,-6.9c0,-0.4 -0.1,-0.7 -0.1,-1.1c0,-0.2 -0.1,-0.2 -0.2,-0.3c-1.5,-0.6 -2.6,-1.6 -2.9,-3.2c-0.2,-1.1 0.2,-2 1.1,-2.7c0.4,-0.3 0.9,-0.5 1.3,-0.8c0.1,-0.1 0.2,-0.1 0.2,-0.3c-0.1,-1.8 -0.1,-3.6 -0.1,-5.3c0,-1.6 0.1,-3.2 0.1,-4.8c0,-0.4 0.1,-0.8 0.1,-1.3c0,-0.2 0,-0.2 0.2,-0.2c1.3,-0.1 2.5,-0.2 3.8,-0.2c1.1,0 1.9,0.5 2.7,1.1c0,0 0.1,0.1 0.1,0.2c0.2,0.8 0.4,1.6 0.6,2.3c0.2,0.8 0.1,1.6 -0.1,2.3c-0.3,0.7 0,1.4 -0.1,2.1c0,0.3 0,0.5 0,0.8c0.3,-0.1 0.5,-0.1 0.7,-0.2c0,0 0.1,-0.1 0.1,-0.2c-0.1,-1.3 -0.1,-2.6 -0.2,-3.9c0,-1.5 0,-2.9 0,-4.4c0.1,-1.5 1.4,-2.7 2.9,-2.9c1.3,-0.1 2.4,0.1 3.5,0.8c0.2,0.1 0.4,0.3 0.6,0.4c0.2,0.1 0.3,0.3 0.3,0.5c0,1.2 0,2.3 0.1,3.5c0,1.1 0.1,2.1 0.1,3.2c0,0 0,0.1 0.1,0.1c0,-0.1 0.1,-0.2 0.1,-0.3c0.4,-1.1 1,-2.1 1.9,-2.8c1.7,-1.4 4.3,-1.2 5.9,0.4c0.3,0.3 0.6,0.6 0.9,1c0,-0.1 0,-0.3 0,-0.4c0,-2.1 0.1,-4.2 0.1,-6.4c0,-0.7 0.1,-1.4 0.6,-2c0.8,-0.9 1.7,-1.2 2.9,-1.1c1.1,0.1 2.2,0.6 3,1.4c0,0 0,-0.1 0,-0.1c0.3,-1.3 1.5,-2.2 3.1,-2.2c1.3,0.1 2.5,0.5 3.4,1.5c0.6,0.6 0.9,1.3 0.9,2.1c0,1.5 -0.1,3.1 -0.2,4.6c0,0 0,0.1 0,0.2c0.1,-0.2 0.2,-0.2 0.2,-0.3c0.7,-1.2 1.8,-2 3.1,-2.4c0.1,0 0.2,0 0.2,0c0.6,0.4 1.3,0.4 2.1,0.3c1.8,-0.1 3.3,0.5 4.4,1.9c0.7,0.9 1.2,1.9 1.5,3c0.4,1.3 0.5,2.7 0.5,4.1c0,2.2 -0.1,4.3 -0.6,6.4c-0.4,1.4 -0.9,2.7 -1.8,3.9c-2.3,2.9 -6.4,3 -8.8,0.3c-0.2,-0.2 -0.3,-0.4 -0.6,-0.7c0,0.5 0.1,0.8 0.1,1.2c0,0.2 0,0.4 -0.1,0.5c-0.8,2 -2.5,2.2 -4,1.8c-0.7,-0.2 -1.4,-0.5 -2.1,-0.9c-0.2,0.3 -0.4,0.7 -0.6,1c-0.8,0.8 -1.8,1 -2.8,0.9c-0.6,-0.1 -1.2,-0.3 -1.9,-0.5c-1.1,1.6 -2.6,2.7 -4.7,2.9C30.8,46.7 29.1,46 27.6,44.6zM13.3,37c0.2,1.6 0.3,3.2 0.5,4.8c0.2,1.7 0.5,3.4 0.7,5.1c0,0.1 0.1,0.3 0.2,0.3c0.6,0.2 1.2,0.4 1.8,0.4c0.4,0 0.6,-0.1 0.5,-0.6c-0.3,-2 -0.7,-4 -0.9,-6c-0.2,-1.5 -0.3,-3.1 -0.4,-4.7c0,-0.2 0,-0.3 0.2,-0.4c1.2,-0.4 2.3,-0.9 3.5,-1.3c0.6,-0.2 1.3,-0.4 1.9,-0.6c0.3,2.6 0.5,5.1 0.8,7.6c-0.5,-0.1 -0.5,0 -0.5,0.4c0.1,0.7 0.5,1.3 1,1.8c0.3,0.3 0.7,0.3 1.1,0.4c0.1,0 0.3,0.1 0.4,0.1c0.2,0 0.5,0 0.7,0s0.4,-0.2 0.3,-0.5c0,-0.2 -0.1,-0.4 -0.1,-0.6c-0.4,-2.5 -0.7,-5 -0.9,-7.5c-0.2,-2.9 -0.4,-5.7 -0.6,-8.6c-0.1,-1.9 -0.1,-3.8 -0.2,-5.7c0,-0.1 -0.1,-0.2 -0.2,-0.3c-0.4,-0.2 -0.9,-0.3 -1.4,-0.2c-0.6,0.1 -0.9,0.4 -0.9,1c0,0.4 0,0.9 0,1.3c0,2.8 0.1,5.5 0.3,8.3c0,0.3 0,0.5 0,0.8c-0.1,-0.1 -0.2,-0.1 -0.2,-0.1c-0.4,-0.3 -0.8,-0.4 -1.2,-0.2c-1.3,0.5 -2.6,1 -3.8,1.4c-0.1,0 -0.2,0.1 -0.4,0.1c0,-0.1 0,-0.1 0,-0.1c-0.1,-2.4 -0.1,-4.8 -0.2,-7.2c0,-0.1 0.1,-0.2 0.2,-0.3s0.2,-0.2 0.2,-0.3c-0.1,-0.5 -0.2,-1 -0.3,-1.5c0,-0.3 -0.2,-0.4 -0.4,-0.4c-0.6,0 -1.2,0 -1.8,0c-0.2,0 -0.3,0.1 -0.3,0.3c0,1.4 -0.1,2.8 -0.1,4.2c0,2.1 0.1,4.1 0.2,6.2c0,0.2 -0.1,0.3 -0.3,0.4c-0.7,0.4 -1.5,0.8 -2.2,1.1c-0.3,0.2 -0.3,0.3 -0.2,0.6c0.2,0.4 0.5,0.8 1,1c0.2,0.1 0.5,0.1 0.7,0C12.5,37.3 12.9,37.2 13.3,37zM53.1,23.5c0,0 -0.1,-0.1 -0.1,-0.1c-0.5,-0.6 -0.9,-0.7 -1.4,0c-0.4,0.5 -0.7,1 -1,1.6c-0.6,1.3 -0.9,2.7 -1.1,4.2c-0.3,2.1 -0.3,4.1 0.3,6.1c0.4,1.3 0.8,2.5 1.8,3.5c1.3,1.4 3.3,1.5 4.6,0.3c0.6,-0.6 1,-1.3 1.3,-2c0.5,-1.3 0.8,-2.6 0.9,-4c0.2,-2.1 0.2,-4.1 -0.2,-6.2c-0.2,-1 -0.5,-1.8 -1.1,-2.6C56,22.9 54,22.7 53.1,23.5zM35.2,37.5C35.2,37.5 35.1,37.5 35.2,37.5c-0.1,0.1 -0.1,0.2 -0.1,0.3c-0.2,0.7 -0.4,1.3 -0.7,2c-0.3,0.7 -0.8,1.3 -1.4,1.7c-1.4,0.9 -2.8,0.4 -3.3,-1.2c0,0 0,-0.1 0,-0.1c-0.3,-1.3 -0.4,-2.6 -0.3,-4c0,-0.2 0,-0.3 0.1,-0.5c0,0 0,0 0.1,0c0,0 0.1,0.1 0.1,0.1c0.4,0.5 0.9,0.8 1.5,0.8c0.9,0 1.5,-0.5 2,-1.3c0.4,-0.8 0.6,-1.6 0.7,-2.4c0.1,-1.4 0,-2.8 -0.2,-4.1c-0.1,-0.9 -0.4,-1.7 -1,-2.4c-0.8,-1 -2.3,-1.4 -3.4,0.1c-0.5,0.7 -0.8,1.5 -1.1,2.3c-0.9,3.4 -1.1,6.8 -0.6,10.2c0.2,1.4 0.7,2.7 1.7,3.7c0.9,0.9 1.9,1.5 3.2,1.5c1.5,0 2.6,-0.9 3.3,-2.1c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.6 -0.3,-1.3 -0.4,-1.9C35.3,39 35.2,38.3 35.2,37.5zM43.6,32.8C43.6,32.8 43.7,32.8 43.6,32.8c0.1,0.6 0.1,1.2 0.1,1.9c0.1,1.5 0.1,2.9 0.2,4.4c0,0.4 0.1,0.8 0.5,1.1c0.5,0.3 1,0.5 1.6,0.6c0.6,0.1 0.7,0 0.7,-0.6c-0.1,-2.2 -0.3,-4.5 -0.3,-6.7c-0.1,-2 0,-4.1 0,-6.1c0,-1.4 0,-2.8 0.1,-4.2c0,-1.6 0.1,-3.3 0.2,-4.9c0,-0.2 0,-0.4 -0.1,-0.5c-0.5,-0.5 -1.2,-0.8 -1.9,-0.7c-0.3,0 -0.4,0.2 -0.5,0.5c-0.1,1.2 -0.2,2.5 -0.2,3.8c-0.1,2.5 -0.1,5.1 -0.2,7.6C43.6,30.2 43.6,31.5 43.6,32.8zM37.3,26.6C37.3,26.6 37.4,26.6 37.3,26.6c0.1,1.8 0,3.6 0.1,5.4c0.1,2.1 0.2,4.2 0.3,6.4c0,0.7 0.1,1.4 0.2,2.1c0,0.2 0.2,0.5 0.3,0.6c0.5,0.4 1.1,0.6 1.8,0.7c0.4,0 0.5,-0.1 0.5,-0.5c-0.2,-2.5 -0.4,-5.1 -0.5,-7.6c-0.1,-2.4 -0.1,-4.7 -0.1,-7.1c0,-2.4 0.1,-4.9 0.1,-7.3c0,-0.3 -0.1,-0.4 -0.3,-0.6c-0.5,-0.4 -1.1,-0.6 -1.7,-0.6c-0.4,0 -0.5,0.1 -0.6,0.5c0,0.8 -0.1,1.7 -0.1,2.5C37.4,22.9 37.3,24.7 37.3,26.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M60.7,53.2c-0.5,0 -0.9,0 -1.4,0c0,-0.1 0,-0.2 0,-0.3c0,-1 0,-2.1 0,-3.1c0,-0.2 0,-0.3 -0.1,-0.5c-0.1,-0.5 -0.5,-0.8 -1,-0.9c-0.5,-0.1 -1,0.2 -1.2,0.6c-0.1,0.2 -0.2,0.5 -0.2,0.8c0,1 0,2 0,3c0,0.1 0,0.2 0,0.3c-0.5,0 -0.9,0 -1.3,0c0,-1.9 0,-3.9 0,-5.8c0.4,0 0.9,0 1.3,0c0,0.3 0,0.5 0,0.8c0.5,-0.6 1.1,-1 1.8,-1c0.8,0 1.3,0.3 1.7,1c0.3,-0.2 0.5,-0.5 0.8,-0.6c1,-0.6 2.4,-0.3 2.9,0.5c0.2,0.4 0.3,0.8 0.3,1.3c0,1.3 0,2.6 0,3.9c-0.4,0 -0.9,0 -1.4,0c0,-0.1 0,-0.2 0,-0.3c0,-1 0,-2 0,-3c0,-0.1 0,-0.2 0,-0.3c-0.1,-0.8 -0.5,-1.2 -1.2,-1.2c-0.7,0 -1.2,0.5 -1.2,1.2c0,0.9 0,1.7 0,2.6C60.7,52.5 60.7,52.8 60.7,53.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M54.2,50.3c0,1.8 -1.4,3 -3.2,3c-1.7,0 -3,-1.3 -3,-3c0,-1.7 1.4,-3.1 3.2,-3.1C52.9,47.2 54.2,48.6 54.2,50.3zM49.3,50.2c0,1 0.8,1.9 1.8,1.9c1,0 1.8,-0.8 1.8,-1.8c0,-1 -0.8,-1.8 -1.8,-1.9C50.1,48.4 49.3,49.2 49.3,50.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M41.4,47.4c0.5,0 1,0 1.5,0c0,0.4 0,0.7 0,1.1c-0.5,0 -1,0 -1.5,0c0,1.6 0,3.1 0,4.7c-0.4,0 -0.9,0 -1.3,0c0,-1.6 0,-3.1 0,-4.7c-0.3,0 -0.5,0 -0.7,0c0,-0.4 0,-0.7 0,-1.1c0.2,0 0.5,0 0.7,0c0,-0.2 0,-0.4 0,-0.6c0,-1.1 0.7,-1.8 1.8,-1.8c0.3,0 0.6,0.1 0.9,0.1c0.1,0 0.2,0.1 0.2,0.2c0,0.3 0,0.6 0,1c-0.5,-0.1 -1,-0.3 -1.4,0.1C41.3,46.7 41.4,47 41.4,47.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M45.3,53.2c-0.5,0 -0.9,0 -1.3,0c0,-1.9 0,-3.9 0,-5.8c0.4,0 0.9,0 1.3,0c0,0.4 0,0.7 0,1.1c0.5,-0.8 1.1,-1.3 2.1,-1.2c0,0.5 0,0.9 0,1.4c-0.1,0 -0.2,0 -0.3,0c-1.1,0.1 -1.7,0.9 -1.7,2.1c0,0.7 0,1.4 0,2.1C45.3,53 45.3,53.1 45.3,53.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M51.3,31.8c0.3,0.1 0.6,0.1 0.8,0.2c0.2,-1.1 0.4,-2.2 0.6,-3.3c0.2,-1.1 0.5,-2.1 1,-3c0.2,-0.3 0.4,-0.6 0.6,-0.8c0.5,-0.5 1.2,-0.3 1.4,0.3c0.2,0.4 0.3,0.9 0.4,1.4c0.2,1.6 0.1,3.3 0,4.9c-0.1,1.4 -0.3,2.7 -0.7,4c-0.2,0.7 -0.5,1.3 -1,1.8c-0.7,0.7 -1.5,0.6 -2.1,-0.1c-0.5,-0.6 -0.7,-1.3 -0.8,-2.1c-0.2,-1 -0.2,-2.1 -0.2,-3.1C51.3,31.9 51.3,31.8 51.3,31.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M31.5,31c0,1 0,1.9 -0.3,2.9c-0.1,0.2 -0.2,0.5 -0.3,0.7c-0.2,0.3 -0.5,0.4 -0.8,0.3c-0.3,-0.1 -0.6,-0.4 -0.6,-0.7c0,-2.2 0.3,-4.4 0.8,-6.5c0,-0.2 0.1,-0.5 0.3,-0.5c0.3,0 0.3,0.3 0.4,0.5c0.3,0.9 0.4,1.9 0.4,2.9C31.5,30.6 31.5,30.8 31.5,31z"/>
+</vector>
diff --git a/res/drawable/icon_hourglass.xml b/res/drawable/icon_hourglass.xml
new file mode 100644
index 0000000..8b7e227
--- /dev/null
+++ b/res/drawable/icon_hourglass.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#00000000"
+        android:pathData="M204,166.6l-1-5.3c-1.1-5.9,0.5-12,4.3-16.7
+		l31.6-35.3c7.5-9.2,10.7-21.3,8.5-33l-8.3-45.9c-1.7-9.6-39.7-10.6-84.7-2.2S74.3,51.2,76,60.8l8.3,45.9
+		c2.1,11.7,9.3,21.9,19.6,27.8l41.9,21.6c5.2,3,8.8,8.1,9.9,14l1,5.3l1.1,6.2l1,5.3c1.1,5.9-0.5,12-4.3,16.7l-31.6,35.3
+		c-7.5,9.2-10.7,21.3-8.5,33l8.3,45.9c1.7,9.6,44.2,16.1,89.2,7.8c45-8.4,75.6-28.5,73.9-38.1l-8.3-45.9
+		c-2.1-11.7-9.3-21.9-19.6-27.8l-41.9-21.6c-5.2-3-8.8-8.1-9.9-14l-1-5.3L204,166.6z"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="11.6824"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M224.6,39.8c1,5.4-27.9,15.4-64.4,22.2
+		c-36.6,6.8-67,7.9-68,2.5c-1-5.4,27.9-15.4,64.4-22.2C193.2,35.5,223.6,34.4,224.6,39.8z"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="3.512"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M262.6,268.1l0.1,0l-69.6-35.4c0,0-44,42.7-56.4,57.3c-2.8,2.6-4.2,5.2-3.8,7.5c1.7,9.6,34.7,13,71.5,6.2
+			c36.9-6.9,63.7-21.4,61.9-31C266,270.9,264.7,269.4,262.6,268.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M232.2,79.2c1.3,7.1-0.5,14.3-5,19.9l-31.6,35.3l-0.2,0.3c-6.8,8.2-13.9,19.8-12,30.4l2,16.5l-3.5,1.1
+			l-5.4-15.4c-1.9-10.5-13.8-19.5-23-24.8l-0.3-0.2l-41.9-21.6c-6.1-3.6-10.4-9.7-11.7-16.8l0.1-1c-1.3-7.2,27.3-18.6,63.9-25.5
+			c36.6-6.8,67.3-6.5,68.7,0.8L232.2,79.2z"/>
+</vector>
diff --git a/res/drawable/icon_party.xml b/res/drawable/icon_party.xml
new file mode 100644
index 0000000..d828103
--- /dev/null
+++ b/res/drawable/icon_party.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#00000000"
+        android:pathData="M76.1,159.7L35.2,312c-1.6,6 5.7,12 11.3,9.3l143.9,-68.6l0.5,-0.6c2.9,-3.6 -20.3,-27.3 -51.9,-53s-59.6,-43.6 -62.5,-40L76.1,159.7z"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="12.0143"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M83.3,175.9c-2.3,2.9,15.6,21.3,40.1,41.3c24.5,19.9,46.3,33.8,48.6,30.9c2.3-2.9-15.6-21.3-40.1-41.3
+			C107.4,186.9,85.6,173.1,83.3,175.9"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M177.3,214.5c16.8-8.7,42.6-13.8,59.7-4.5c10.7,5.9,16.9,17.1,18.2,33.3l17.2-1.4
+			c-2.3-27.8-16-40.9-27.1-47c-22.7-12.5-47.1,6.9-68.5,18.1L177.3,214.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M111.4,161.8l2,0.1c4.8-14.5,7.3-35.4-2.4-50.9c-10.9-17.5-19.4-21.2-39.8-24l-2.3,17.1
+			c20.6,2.8,31.6,15.9,36.4,23.5C112.3,138.7,114.7,152.1,111.4,161.8"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M156.3,196.8c12-12.8,36.8-32.4,65-47.4c22.8-12.1,56-25.6,84.4-20.8l2.9-17c-58.4-9.8-124.3,53.6-153,84.1
+			L156.3,196.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M138,177.1l1.8-0.3c0.7-1.7,1.4-3.6,2.2-5.6c11.9-29.8,48.2-78.7,18.7-104l-11.3,13.1
+			c20.2,17.3,0.3,67.2-9.2,91.1C139.4,173.5,138.7,175.4,138,177.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M300.8,175.1 L288.3,176 L280.5,166.3 L277.5,178.4 L265.8,182.9 L276.5,189.4 L277.1,201.9 L286.6,193.8
+			L298.7,197.1 L293.9,185.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M246.6,37.2 L226.6,51 L203.8,42.3 L210.7,65.6 L195.4,84.5 L219.8,85.1 L233.1,105.5 L241.2,82.6
+							L264.7,76.3 L245.4,61.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M144.5,121 L139.1,123.4 L134,120.4 L134.7,126.3 L130.2,130.2 L136.1,131.4 L138.4,136.8 L141.3,131.7
+			L147.2,131.1 L143.2,126.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M230.5,166.9c-2.2,2.7-1.8,6.7,0.9,8.9c2.7,2.2,6.7,1.8,8.9-0.9c2.2-2.7,1.8-6.7-0.9-8.9
+			C236.6,163.8,232.7,164.2,230.5,166.9"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M205.6,101.8c-0.7,0.9-0.6,2.1,0.3,2.8c0.9,0.7,2.1,0.6,2.8-0.3c0.7-0.9,0.6-2.1-0.3-2.8
+			C207.6,100.8,206.3,100.9,205.6,101.8"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M210.6,235.4c-2,2.4-1.6,6,0.8,7.9c2.4,2,6,1.6,7.9-0.8c2-2.4,1.6-6-0.8-7.9
+			C216.1,232.6,212.5,233,210.6,235.4"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M172.8,138.8c-2.7,3.3-2.2,8.1,1.1,10.7c3.3,2.7,8.1,2.2,10.7-1.1c2.7-3.3,2.2-8.1-1.1-10.7
+			C180.3,135.1,175.5,135.6,172.8,138.8"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M123.3,43c-1.7,2.1-1.4,5.3,0.7,7c2.1,1.7,5.3,1.4,7-0.7c1.7-2.1,1.4-5.3-0.7-7
+			C128.2,40.5,125.1,40.8,123.3,43"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M326.1,141.1c-1.7,2.1-1.4,5.3,0.7,7c2.1,1.7,5.3,1.4,7-0.7c1.7-2.1,1.4-5.3-0.7-7
+							C330.9,138.7,327.8,139,326.1,141.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M34.5,132c-2.8,3.4-2.3,8.4,1.1,11.2c3.4,2.8,8.4,2.3,11.2-1.1c2.8-3.4,2.3-8.4-1.1-11.2
+			C42.3,128,37.2,128.5,34.5,132"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M252.1,279c-0.9,1.1-0.8,2.8,0.4,3.7c1.1,0.9,2.8,0.8,3.7-0.4c0.9-1.1,0.8-2.8-0.4-3.7
+			C254.7,277.7,253,277.9,252.1,279"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M134.3,278.8c-23,-2.7 -69.1,-46.9 -62.9,-94.6"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="2.9819"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M89.1,300.1c-15.1,-6.2 -37.2,-37.1 -26.6,-76.9"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="2.9819"/>
+</vector>
diff --git a/res/drawable/icon_peace.xml b/res/drawable/icon_peace.xml
new file mode 100644
index 0000000..20d96ff
--- /dev/null
+++ b/res/drawable/icon_peace.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="1008"
+    android:viewportHeight="1008">
+
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M398.1,414.5c-1.4-8.5-3.1-17.9-4.5-27.4c-5.9-40-12-80-17.5-120.1c-4-28.9-7.7-57.8-10.5-86.8
+c-2.4-24.9-1.4-49.7,9.5-73c14-29.9,37.7-47,70.5-50.1c42.9-4,73.2,15.9,94.3,51.7c13.1,22.2,19.6,46.9,24.9,71.9
+c6.5,31.1,12.7,62.3,19.1,93.4c0.1,0.6,0.3,1.2,0.8,3.4c1.1-2.9,1.7-4.5,2.2-6.1c5.7-16.5,11.2-33.1,17-49.5
+c6.5-18.5,15.9-35.5,28.3-50.8c29.7-36.5,72.5-44.5,113.6-21.3c31.2,17.6,44.6,45.2,45.4,80.1c0.5,23.3-5.2,45.5-11,67.8
+c-14.2,54.8-28.2,109.5-42.2,164.3c-0.6,2.5-1.6,4.6,1.3,7c29.5,24.3,45.2,56.4,52.5,93.3C805,628.4,793.7,691,764.7,751
+c-16.2,33.5-36.6,64.1-60,92.9c-25.7,31.6-58.8,52.1-96.9,65.1c-32.5,11.1-66.1,17.2-100.3,18.7c-28.4,1.2-56.9,1.2-85.3,0
+c-34.8-1.5-68.2-9.6-98.1-28.7c-22.5-14.5-39.8-34.1-55.5-55.5c-31.4-42.6-49.3-90.8-61.8-141.8c-7.1-28.9-14.2-57.8-19.2-87.2
+c-4.2-24.4-7.2-48.8-1.5-73.4c7.9-34.2,27.8-57.2,62.2-66.7c14.5-4,28.9-7.7,44.2-7.3c1.2,0,2.9-0.9,3.5-1.9
+c14.2-24.4,36.4-37.2,63.3-43.1C371.9,419.4,384.8,417.1,398.1,414.5z
+M582.1,332.8c-0.3,0-0.5-0.1-0.8-0.1
+c-1.7-8.8-3.4-17.5-5.2-26.3c-9.3-45.3-18.4-90.7-28.1-135.9c-4.8-22.2-12.1-43.7-25.2-62.6c-17.6-25.3-41.3-39.3-72.9-37.1
+c-30,2.2-51.3,17.2-63,45c-9.9,23.5-9.3,48.2-6.4,72.8c3.8,32.6,7.9,65.1,12.5,97.6c5.9,41.2,12.4,82.3,18.7,123.4
+c1.1,7.3,2.4,14.6,3.7,22.4c-2-0.2-3.3-0.5-4.6-0.5c-7.5-0.3-15.1-1.9-22.3-0.7c-14.5,2.5-29,5.9-43.1,10.3
+c-15.6,4.9-27.5,15.4-36.1,29.3c-2.4,3.9-4.4,8.1-6.1,11.2c-7.5,0-14.4-0.8-21,0.2c-10.5,1.5-20.9,3.8-31.2,6.5
+c-25.2,6.7-41.3,23.1-49.1,47.9c-7.3,23.3-5.1,46.6-1.5,70.2c5.6,37.3,15.2,73.6,24.9,110c7.7,29.2,17.5,57.6,32.6,84
+c13.7,23.9,28.9,46.8,48.5,66.4c29.5,29.5,66.2,42.5,106.8,46.2c29.6,2.7,59.2,2.8,88.8,1c31.9-1.9,63.3-6.5,93.8-16
+c36.1-11.3,68.4-28.8,93.4-57.9c25.3-29.5,46.6-61.6,63.4-96.6c27.3-56.9,38-116.1,25.5-178.6c-7.2-36-23.1-66.9-53-89.4
+c-3.4-2.5-3.9-4.7-2.9-8.6c15.5-59.9,30.9-119.9,46.3-179.8c4.9-19.1,9.4-38.1,8.8-58c-0.9-27.2-10.6-49.5-34.2-64.7
+c-35.8-22.9-73.3-17-100.1,15.9c-10.8,13.3-19.2,28.1-24.9,44.2c-9,25.6-17.5,51.3-26.1,77.1C588.6,311.9,585.4,322.4,582.1,332.8z" />
+    <path
+        android:fillColor="?attr/fillColorSelector"
+        android:pathData="M577.2,419.2c14.4-46,28.5-91.4,42.9-136.7c5-15.9,10.5-31.6,16.1-47.2c5.3-14.8,12.7-28.6,22.4-41
+c20.3-25.9,49.1-29.8,75.8-10.4c18.6,13.5,23.5,32.6,22.3,54.2c-1.2,21.3-7.8,41.5-13,61.9c-15.4,60.4-31,120.8-46.4,180.7
+c8.5,6.7,17.2,12.6,24.8,19.7c20.8,19,30.9,43.7,36,70.8c11.6,61.4-0.6,118.7-29.1,173.4c-15.4,29.7-34.2,57.1-56,82.5
+c-21.4,24.9-49.1,39.9-79.8,50c-35.4,11.6-72.1,16.3-109.1,16.8c-23.4,0.3-47-0.3-70.4-2c-46.4-3.3-83.5-23.8-111.6-61.6
+c-30.6-41.1-49.2-87-61.2-136.5c-7.7-31.4-15.1-62.7-20.3-94.6c-2.9-18-4.3-36.1,0.5-54c5.2-19.3,17-32,36.6-37
+c6.9-1.8,13.8-3.8,20.8-5.1c13.5-2.5,26.2-0.3,37.8,8.6c1-4.3,1.7-8.1,2.8-11.8c5.9-22.1,19.5-36.6,42.2-42
+c7.9-1.9,15.7-4.4,23.7-5.8c17.5-3.2,33.5,0.2,46.8,13.2c3-4.1,5.9-7.9,8.5-11.9c0.5-0.8,0.3-2.2,0.1-3.3
+c-12.9-65.7-22.1-132-31-198.3c-3.7-27.9-7-55.9-9.1-83.9c-0.9-11.4,0.4-23.4,2.9-34.6c10.8-48.3,64.5-50.9,89.4-28.5
+c13.4,12.1,22.4,27.2,27.2,44.1c7,24.4,12.9,49.2,18.1,74.1c13.2,64,25.6,128.2,38.4,192.3C576.4,416.6,576.8,417.7,577.2,419.2z
+M289,752.9c10.3,23.9,24,45,39.4,65.2c18.9,24.8,43.7,39.2,74.5,44.2c23.8,3.8,47.8,4.1,71.7,3.8c36.6-0.4,72.8-4.1,107.9-15.2
+c27.1-8.6,51.6-21.4,70.3-43.6c21.5-25.4,39.8-52.9,54.6-82.8c23.7-47.9,32.9-97.7,22.5-150.7c-6.5-32.8-23.9-56.9-54.1-71.6
+c-19.4-9.5-39.8-16.1-60.7-21.1c-33.4-8.1-67.4-12.5-101.6-15.9c-9.8-1-19.6-1.8-29.4-1.9c-13.8-0.2-26.6,9.5-29.1,20.5
+c-3.4,14.8-1.1,28.1,8.8,39.8c9.3,11,21.7,17.5,34.9,22.4c24.2,9,49.6,12.7,75.2,15c8.3,0.7,16.6,1,24.9,1.5
+c12.9,0.8,22.8,8.8,25.8,20.6c3.2,12.4-1.4,24.2-12.6,31c-26.7,16.3-53.6,32.3-80.3,48.6c-17.4,10.7-31,24.6-35.6,45.5
+c-2.9,13.2-3.2,26.5-1.8,39.8c1.4,13.6,3.7,27,5.6,40.5c1.4,10.1-6.3,18-16.1,16.4c-6.2-1-10.8-5.5-11.8-13.1
+c-2.4-19.3-5.3-38.6-6.2-58c-1.2-24.7,4.2-48,19.9-68c11-14,25.4-23.8,40.6-32.8c21.8-12.9,43.4-26,65.1-39
+c1.3-0.8,2.5-1.7,4.8-3.3c-46.5-2.8-91.4-7.3-131.3-29.3c0.9,24,1.8,48.1,2.8,72.2c0.9,21.2-4.3,40.9-13.5,59.7
+c-6.8,13.9-15.1,26.7-27.6,36.3c-17.1,13.1-37.1,12.7-52.7-2.1c-6.5-6.2-11.3-14.3-16.9-21.5c-0.9-1.2-1.6-2.6-2.6-4.3
+c-1.8,4.7-3.1,8.9-4.9,12.8C337.2,743.3,318.8,755.1,289,752.9z
+M552.5,440.9c-1.6-8.7-3.2-17.2-4.9-25.6
+C533.8,346,519.9,276.6,506,207.4c-3.9-19.6-7.8-39.2-15.9-57.6c-4-9.2-8.8-18-17-24.3c-16.1-12.5-37.5-5.7-42.6,13.9
+c-1.8,6.8-3,14.2-2.5,21.2c1.9,24.9,4,49.8,7.4,74.5c7.1,51.8,14.9,103.4,22.6,155.1c2.4,15.8,5.5,31.4,8.3,47.4
+C495.5,431.4,523.6,439.6,552.5,440.9z
+M671.4,467.9c0,0,0.3-0.5,0.5-1.2c17.6-68.5,35.2-136.9,52.6-205.4
+c3.1-12.1,5.5-24.3,3.7-37c-1.9-13.5-10.8-20-22.7-23.6c-10.7-3.3-17.9,2.5-24.1,10.1c-8.5,10.6-15.1,22.4-19.2,35.3
+c-21.1,66.2-42,132.5-62.9,198.8c-0.4,1.2-0.4,2.5-0.4,2.8C623.2,454.5,647,461.1,671.4,467.9z
+M441.3,618.3
+c-0.4,0-0.8-0.1-1.2-0.1c-0.9-30.3-3.4-60.5-10.4-90.1c-3.1-13.3-6.5-26.5-14.2-38.2c-5.8-8.7-13.9-12.3-24.1-10.3
+c-8.5,1.7-16.8,4.1-25.2,6.1c-10,2.4-16.8,8.8-19,18.5c-2.2,9.8-4.5,20.2-3.6,30c3.9,41.7,11.3,82.8,23.6,122.8
+c5,16.4,11,32.6,22.2,46c8.2,9.9,14.7,10.1,23.7,1.1c12.1-12.1,19.9-27,23.4-43.4C439.7,646.9,439.9,632.5,441.3,618.3z
+M245.3,569.8c0.9,8.3,1.4,14.8,2.4,21.2c4.8,29,9.1,58.1,18.4,86.2c5,15.1,10.7,29.8,21.7,41.7c8.6,9.3,16.5,9.4,25.3,0.6
+c9.3-9.3,14.9-20.8,15.7-33.7c0.7-11-0.8-22.2-1.8-33.3c-2.7-29.7-6-59.3-14-88.1c-2.4-8.4-5.6-16.7-9.4-24.6
+c-3.8-7.8-10.8-11.1-19.6-9.1c-7,1.6-13.9,3.4-20.8,5.2c-7.3,1.8-12.1,6.6-13.9,13.6C247.3,556.7,246.3,564.2,245.3,569.8z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/icon_pin.xml b/res/drawable/icon_pin.xml
new file mode 100644
index 0000000..4c3ac52
--- /dev/null
+++ b/res/drawable/icon_pin.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M261.1,91.8C253.6,52,219.5,23.2,180,23c-4,0.4-7.9,0.5-11.9,1.1c-19.4,2.9-35.9,11.8-49.1,26.7
+			c-17.2,19.5-24,42.5-20.9,68.6c1.4,11.8,5.4,22.9,10.9,33.3c6.9,12.9,15.1,25,23.3,37c9.9,14.5,20,28.7,28.9,43.8
+			c6,10.2,11.6,20.6,15.2,32c0.6,1.9,1.6,2.8,3.1,2.8c1.5,0,2.5-0.9,3.2-2.8c1.1-3.1,2.2-6.1,3.5-9.1c5.5-12.7,12.7-24.4,20.4-35.8
+			c9.7-14.4,19.7-28.6,29.4-43c8.3-12.3,16.1-24.9,21.1-39.2C262.5,123.2,264.1,107.7,261.1,91.8 M179.1,148.7
+			c-23.8-0.5-42.3-20.6-42.2-44.4c0.1-24.4,19.2-44.1,43.1-44.1c23.9,0,43,19.7,43,44.4C223,129,203.6,149.2,179.1,148.7"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M245.2,278.5c-9.7-4.7-20-7.4-30.6-9.2c-1.6-0.3-3.5-1.1-4.7-0.5c-1.3,0.7-1.9,2.7-2.7,4.2
+			c-1.7,3.2-3.4,6.5-5.2,9.9c3.4,0.5,6.5,0.9,9.5,1.4c9.6,1.7,19.1,3.9,28,8.4c3.2,1.6,6.3,3.5,8.7,6.4c1.8,2.2,1.9,3.7-0.1,5.8
+			c-1.7,1.8-3.7,3.4-5.8,4.7c-7,4.3-14.8,6.6-22.7,8.4c-14.5,3.3-29.2,4.4-44,4c-11.8-0.3-23.6-1.6-35.1-4.3
+			c-7.8-1.9-15.4-4.2-22.2-8.7c-1.9-1.3-3.6-2.9-5.2-4.6c-1.4-1.5-1.3-3,0-4.6c1.3-1.5,2.7-2.9,4.3-4.1c4.6-3.3,9.9-5.3,15.2-7.1
+			c8.4-2.7,17-4.3,25.8-5.4c0-0.3,0-0.5-0.1-0.7c-2.2-4.4-4.5-8.7-6.8-13c-0.2-0.4-1-0.7-1.5-0.6c-7.8,1.8-15.7,3.3-23.4,5.6
+			c-8.3,2.5-16.1,6.2-22.5,12.6c-4.7,4.7-7.4,10.3-6.6,17.3c0.7,6,3.9,10.4,8.2,14.1c5.5,4.8,11.9,7.9,18.7,10.3
+			c17.4,6.3,35.5,8.4,53.8,8.6c7.4,0.1,14.8-0.3,22.2-0.9c12.3-1,24.3-3.2,36-7.4c7.5-2.7,14.6-6,20.6-11.6
+			c9.3-8.7,9.7-20.8,0.9-30.1C254.2,283.5,249.8,280.7,245.2,278.5"/>
+</vector>
diff --git a/res/drawable/icon_rain.xml b/res/drawable/icon_rain.xml
new file mode 100644
index 0000000..510aa08
--- /dev/null
+++ b/res/drawable/icon_rain.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="72.0"
+    android:viewportWidth="72.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M52,46.1c0.8,1.1 1.6,2.2 2.3,3.3c0.8,1.1 1.5,2.3 1.9,3.6c1,3 -1.2,6.2 -4.4,6.2c-2.4,0 -4.4,-1.6 -4.7,-4c-0.2,-1 0,-1.9 0.2,-2.8c0.1,-0.4 0.2,-0.8 0.2,-1.2c0,0 -0.1,-0.1 -0.1,-0.1c-0.1,0.1 -0.1,0.2 -0.2,0.3c-3.4,3.8 -6.8,7.6 -10.2,11.4c-0.3,0.3 -0.6,0.6 -1,0.5c-0.6,0 -1,-0.6 -0.9,-1.2c0.1,-0.6 0.4,-1.2 0.6,-1.8c1.4,-4.3 2.9,-8.6 4.3,-12.9c0,-0.1 0.1,-0.2 0.1,-0.4c-0.2,0 -0.3,0 -0.4,0c-2.1,0 -4.2,0 -6.3,0c-1,0 -1.4,-0.3 -1.6,-1.2c-2.4,-0.1 -4.8,-0.6 -7.1,-1.7c0.2,0.4 0.3,0.8 0.4,1.2c1.2,3.7 -1.4,7.8 -5.2,8.4c-3.6,0.5 -6.8,-1.8 -7.5,-5.4c-0.2,-1 0,-2.1 0.1,-3.1c0.3,-2.1 0.9,-4.1 1.5,-6.1c0,-0.1 0.1,-0.2 0.1,-0.3c-0.1,0 -0.2,-0.1 -0.4,-0.1c-2.3,-0.9 -4.4,-2.2 -6,-4c-3.5,-3.9 -3.4,-9.3 0.2,-13.1c2.2,-2.3 4.9,-3.7 7.9,-4.5c0.8,-0.2 1.6,-0.3 2.3,-0.5c0.1,0 0.3,-0.1 0.3,-0.2c0.9,-4.8 3.6,-8.3 7.9,-10.5c6.1,-3.1 12.2,-3 18.1,0.4c2.9,1.7 5.1,4.1 6.3,7.3c0.1,0.2 0.2,0.2 0.4,0.3c3.3,0.5 6.3,1.7 8.8,3.8c2.2,1.8 3.8,4.1 4.4,6.9c0.7,3.5 -0.2,6.6 -2.4,9.3c-2.2,2.8 -5.2,4.4 -8.6,5.4c-1.9,0.5 -3.8,0.7 -5.7,0.7c-0.3,0 -0.5,0.1 -0.6,0.5c0.1,0 0.3,0 0.4,0c2.2,0 4.4,0 6.6,0c0.1,0 0.2,0 0.3,0c0.5,0 0.9,0.2 1.1,0.7c0.2,0.5 0,0.9 -0.3,1.3c-1,1.2 -2.1,2.3 -3.1,3.5C52.1,46 52.1,46.1 52,46.1zM33.3,37.5c0.2,-0.8 0.3,-1.5 0.5,-2.3C34,34.1 34,33 34.5,32c-2.5,-1.6 -4.5,-3.8 -5.8,-6.6c0.1,0 0.1,0.1 0.2,0.1c1.5,1.6 3.2,2.9 5.1,3.7c5.2,2.3 10.4,2.2 15.6,0.2c0.9,-0.4 1.8,-0.8 2.7,-1.2c0,0 0,0.1 0,0.1c-0.7,1.8 -1.3,3.6 -2,5.4c0,0.1 -0.1,0.2 -0.2,0.2C50,34 49.9,34 49.8,34.2c-0.4,0.9 -0.8,1.9 -1.2,2.8c0,0.1 -0.1,0.2 -0.1,0.4c0.2,0 0.3,0 0.4,0c1,-0.1 2.1,-0.2 3.1,-0.4c3,-0.7 5.7,-2 7.8,-4.4c2.6,-3 3,-7 0.9,-10.3c-1.3,-2.1 -3.2,-3.6 -5.5,-4.6c-1.9,-0.9 -3.8,-1.3 -5.9,-1.5c-0.3,0 -0.4,-0.2 -0.5,-0.4c-0.9,-3.2 -2.8,-5.5 -5.6,-7.2c-3.2,-2 -6.8,-2.7 -10.5,-2.2c-3.3,0.5 -6.3,1.8 -8.6,4.3c-1.9,2 -3.1,4.3 -3.2,7.1c0,0.4 -0.1,0.8 -0.1,1.2c-0.2,0 -0.3,0 -0.4,0c-1.6,0.1 -3.2,0.3 -4.7,0.8c-2.4,0.8 -4.6,1.9 -6.2,3.9c-1.4,1.7 -2,3.6 -1.6,5.7c0.3,1.8 1.3,3.2 2.6,4.4c2.2,2 4.8,3 7.6,3.4c1.1,0.2 2.2,0.2 3.4,0.3c0.2,0.5 0.4,1 0.6,1.5c0.7,1.3 1.8,2.1 3.1,2.7c1.5,0.8 3.2,1.3 4.8,1.5c0.7,0.1 1.4,0.1 2.1,0.2c0.2,-1.3 0.5,-2.6 0.7,-3.8c-1.6,-0.4 -3,-1 -4.2,-1.8c-1.3,-0.9 -2.8,-2.6 -3,-3.4C28.2,36.8 31.5,37.5 33.3,37.5zM38.3,58.5C38.3,58.5 38.3,58.5 38.3,58.5c4.9,-5.4 9.7,-10.7 14.6,-16.2c-0.2,0 -0.3,0 -0.5,0c-2,0 -4,0 -6,0c-0.2,0 -0.4,0 -0.5,0c-0.8,-0.2 -1.1,-1 -0.8,-1.8c0.8,-1.8 1.5,-3.6 2.3,-5.5c0.1,-0.2 0.1,-0.3 0.2,-0.6c-0.1,0 -0.2,0 -0.3,0c-3.2,0.5 -6.4,0.2 -9.5,-0.9c-0.6,-0.2 -1.2,-0.2 -1.8,-0.2c-0.8,4 -1.5,7.9 -2.3,11.9c0.2,0 0.3,0 0.5,0c2.2,0 4.4,0 6.6,0c1.1,0 1.7,0.8 1.3,1.8c-0.9,2.7 -1.8,5.4 -2.7,8C39,56.3 38.7,57.4 38.3,58.5zM15.5,39.3c0,0 0,0.1 0,0.1c-0.6,2 -1.2,4.1 -1.5,6.2c-0.1,0.9 -0.3,1.9 -0.1,2.8c0.6,2.8 3.2,4.6 6,4c2.8,-0.5 4.7,-3.4 4,-6.1c-0.3,-1.1 -0.9,-2.1 -1.3,-3.1c-0.1,-0.2 -0.3,-0.4 -0.4,-0.5c-0.9,-0.7 -1.6,-1.6 -2.2,-2.6c-0.1,-0.1 -0.2,-0.2 -0.4,-0.2c-0.4,-0.1 -0.8,-0.1 -1.2,-0.1C17.3,39.6 16.4,39.4 15.5,39.3zM51.2,47c-0.6,0.7 -1.3,1.4 -1.9,2.1c0,0.1 -0.1,0.1 -0.1,0.2c-0.5,1.7 -1,3.4 -1.1,5.2c-0.1,2.3 2.1,4.1 4.3,3.6c2.3,-0.5 3.5,-2.8 2.6,-5c-0.6,-1.4 -1.4,-2.7 -2.3,-4C52.3,48.4 51.7,47.7 51.2,47z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M25.6,63.4c0.1,-1.2 0.4,-2.6 0.8,-4c0.3,-1.1 0.7,-2.1 1.1,-3.2c0.4,-1 1,-1.2 1.8,-0.4c0.8,0.9 1.6,1.8 2.3,2.8c0.7,1.1 1.4,2.2 1.9,3.4c1.1,2.7 -0.9,5.7 -3.9,5.6C27.4,67.7 25.5,65.8 25.6,63.4zM28.6,56.8c-0.1,0.1 -0.1,0.2 -0.1,0.3c-0.7,1.7 -1.2,3.4 -1.5,5.1c-0.1,0.7 -0.3,1.4 -0.1,2c0.4,1.6 2.1,2.6 3.7,2.1c1.6,-0.5 2.4,-2.2 1.8,-3.8c-0.7,-1.8 -1.8,-3.3 -3,-4.8C29.1,57.4 28.9,57.1 28.6,56.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M11.3,27c2.9,4.4 6.9,5.9 12,5.1c-0.1,0.1 -0.1,0.2 -0.2,0.3c-0.4,0.6 -0.9,1.1 -1.2,1.7c-0.3,0.5 -0.6,0.6 -1.2,0.5c-4.4,-0.3 -8.2,-3.2 -9.2,-7.1C11.4,27.4 11.4,27.3 11.3,27z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M15.5,46.8c1,2.4 4.8,2.9 6.4,0.5c0.2,0.7 0.2,1.4 -0.2,2c-0.8,1.3 -2,1.8 -3.4,1.6c-1.4,-0.1 -2.4,-0.8 -3,-2.1C15.1,48.1 15.1,47.5 15.5,46.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M53.9,54.5c0.3,0.7 0,1.5 -0.6,2c-0.9,0.7 -2.4,0.7 -3.3,0c-0.8,-0.6 -1,-1.5 -0.7,-2.4c0.5,0.9 1.2,1.4 2.2,1.5C52.5,55.7 53.3,55.4 53.9,54.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M27.7,63.3c0.7,1.4 2.7,1.8 3.8,0.3c0.2,0.6 0,1.3 -0.6,1.7c-0.8,0.6 -2,0.5 -2.7,-0.1C27.6,64.7 27.4,64 27.7,63.3z"/>
+</vector>
diff --git a/res/drawable/icon_snow.xml b/res/drawable/icon_snow.xml
new file mode 100644
index 0000000..5dd65cd
--- /dev/null
+++ b/res/drawable/icon_snow.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+    android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M61.5,401.4c17.4,-30.1 34.5,-59.8 52,-90.1c15.3,8.8 30.4,17.5 46.6,26.8c-2.7,-10.3 -5.2,-19.4 -7.7,-29.1c3.7,-1.1 7.2,-2.1 10.7,-3c16.4,-4.5 32.8,-8.8 49.1,-13.4c2.5,-0.7 5.1,-2.3 7,-4.2c17.2,-16.3 34.2,-32.6 52.6,-50.2c6.2,7.2 13.7,15.8 21.2,24.4c0.6,-0.4 1.3,-0.9 1.9,-1.3c0,-18 0,-36.1 0,-54.5c34.8,0 69.1,0 104.2,0c0,17.2 0,34.5 0,51.8c0.5,0.2 0.9,0.4 1.4,0.5c6.4,-6.9 12.8,-13.8 20.2,-21.9c8.6,9.1 16.2,17.2 23.9,25.2c4.3,4.4 9,8.4 13,13.2c5.8,7 13.1,10.4 21.9,12.4c21.7,5.1 43.2,11 65.4,16.7c-2.9,11.4 -5.7,22.5 -8.8,34.8c16.8,-9.7 32.5,-18.7 48.7,-28.1c14.2,24.6 28.3,49 42.9,74.1c6.5,-10.2 13.5,-19.2 18.3,-29.3c2.5,-5.3 1.2,-12.4 1.5,-18.7c0.4,-9 0.7,-17.9 1.1,-27.1c4.6,0 8.8,0 14,0c-5.8,-6.5 -11.2,-12.6 -16.8,-19c16.6,-14.9 33,-29.7 49.8,-44.8c5.2,5.7 10.3,11.2 16.1,17.5c0.4,-3.9 0.8,-6.9 1.2,-10.4c12.2,0.6 24.4,1.2 36.5,1.6c2.2,0.1 4.6,-0.4 6.6,-1.4c12.5,-6.3 24.8,-12.8 37.6,-19.4c2.2,4 4.2,7.7 6.8,12.4c2.8,-8.5 5.4,-16.1 8.1,-24.3c21.3,6.9 42.2,13.7 63.7,20.7c-2.4,7.5 -4.6,14.7 -7.2,23c3.7,-1.9 6.5,-3.2 9.6,-4.8c5.2,10 10,20 15.4,29.7c1.8,3.3 4.6,6.5 7.8,8.6c11.7,7.9 23.7,15.3 35.9,23.1c-2.4,3.9 -4.6,7.5 -7.4,12.1c8.8,-1.8 16.6,-3.4 25.1,-5.2c4.7,21.9 9.3,43.6 13.9,65.6c-7.8,1.7 -15,3.3 -23.2,5.1c3.3,2.4 5.7,4.1 8.6,6.2c-6.6,10.3 -12.9,20.4 -19.6,30.3c-2.7,4 -4,8.2 -4.1,13c-0.3,12.1 -0.9,24.2 -1.4,36.5c-4.6,0 -8.9,0 -13.9,0c5.9,6.6 11.2,12.6 16.8,18.9c-16.7,15 -33.1,29.8 -49.9,44.9c-5.3,-5.8 -10.4,-11.4 -16.2,-17.8c-0.3,4 -0.5,6.9 -0.8,10c-5.5,0 -10.7,0.1 -16,0c-7.7,-0.3 -15.3,-0.9 -22.9,-1.1c-2.2,0 -4.6,0.6 -6.6,1.6c-12,6.1 -23.9,12.3 -36.1,18.7c-2.2,-4.1 -4.2,-7.8 -6.8,-12.4c-2.8,8.4 -5.3,16 -8.1,24.3c-21.2,-6.9 -42.2,-13.7 -63.7,-20.7c2.3,-7.5 4.6,-14.6 7.1,-22.8c-3.7,1.8 -6.4,3 -9.5,4.5c-3.7,-7.1 -8,-13.9 -10.9,-21.2c-4.7,-11.9 -12.6,-20.2 -23.8,-26.1c-7.5,-3.9 -14.4,-9 -22,-13.9c2.4,-3.9 4.6,-7.5 7.5,-12.1c-8.9,1.8 -16.7,3.4 -25,5.1c-1.9,-8.4 -3.7,-16.6 -5.5,-24.7c-0.3,0 -0.6,0.1 -0.9,0.1c-5.4,20.4 -10.8,40.7 -16.1,61.2c-0.5,1.8 0.1,3.9 0.6,5.8c6,21.8 12.1,43.6 18.3,66c-11.2,3.2 -22.3,6.3 -34.6,9.8c16.6,9.6 32.4,18.8 48.7,28.2c-17.3,29.9 -34.4,59.7 -52,90.1c-15.3,-8.8 -30.5,-17.5 -46.7,-26.8c2.7,10.3 5.2,19.5 7.7,29.1c-15.7,4.3 -30.8,9.2 -46.2,12.4c-14.4,3.1 -25.8,9.4 -35.7,20.5c-11.7,12.9 -25.2,24.2 -38.6,36.8c-6.7,-7 -14.6,-15.4 -22.6,-23.7c-0.4,0.3 -0.8,0.6 -1.2,0.8c0,18.1 0,36.2 0,54.6c-34.7,0 -69.1,0 -104,0c0,-17.4 0,-34.8 0,-53.5c-7.5,8 -14.1,15.1 -21.7,23.3c-10.9,-11.4 -20.7,-21.8 -30.6,-32.1c-5.6,-5.7 -11.2,-11.4 -17.1,-16.8c-1.5,-1.4 -3.7,-2.2 -5.7,-2.7c-20.9,-5.5 -41.9,-10.8 -62.8,-16.2c-1.1,-0.3 -2.2,-0.7 -3.8,-1.3c2.9,-11.3 5.7,-22.5 8.8,-34.6c-16.7,9.6 -32.6,18.8 -48.8,28.1c-17.4,-30.1 -34.6,-59.9 -52,-90.1c15.4,-8.9 30.4,-17.6 46.6,-27C98.2,581 89,578.5 79.4,576c4.4,-16.5 8.1,-32.7 13,-48.5c3.1,-10 2.9,-19.1 -0.2,-29.1c-6.1,-19.3 -11,-39 -16.6,-59c11.3,-3.2 22.5,-6.3 34.6,-9.7C93.6,420 77.8,410.9 61.5,401.4zM84.3,616.8c12,20.8 23.8,41.1 35.7,61.8c22.7,-13.1 44.9,-25.9 68.3,-39.4c-5.1,19.8 -9.8,38 -14.5,56.5c1.3,0.5 2.2,0.9 3.1,1.1c15.9,4.1 31.9,8.3 47.9,12.2c5.7,1.4 10.4,3.6 14.4,8.1c5.1,5.7 10.8,10.8 16.2,16.4c6,6.2 11.8,12.5 18.4,19.6c13.3,-13.3 25.6,-25.5 38.3,-38.1c0,25.5 0,50.7 0,75.8c24,0 47.4,0 71.5,0c0,-25.9 0,-51.5 0,-77.2c0.5,-0.3 1.1,-0.7 1.6,-1c12.9,13.9 25.7,27.7 37.7,40.6c11.1,-10.5 21.3,-19.2 30.3,-29c9.2,-10 18.9,-18.5 33.1,-20.1c0.3,0 0.7,-0.1 1,-0.2c12.2,-3.3 24.3,-6.6 36.9,-10.1c-4.6,-17.1 -9.1,-33.8 -14,-51.7c23,13.3 44.7,25.8 66.9,38.5c12,-20.8 23.8,-41.1 35.7,-61.8c-22.8,-13.2 -45.1,-26.1 -68.3,-39.5c19.5,-5.4 37.9,-10.6 56.4,-15.8c-4.6,-16.6 -8.7,-32.5 -13.5,-48.2c-2.2,-7.2 -2.2,-13.7 -0.1,-20.8c4.5,-15.2 8.2,-30.7 12.3,-46.4c-17.1,-4.6 -33.9,-9 -51.8,-13.8c23,-13.3 44.9,-25.9 66.9,-38.7c-12.1,-20.8 -23.9,-41.2 -35.7,-61.8c-22.9,13.2 -45.2,26.1 -68.3,39.4c5,-19.4 9.7,-38 14.5,-56.7c-21.5,-5.6 -42.3,-10.9 -63,-16.5c-2.3,-0.6 -4.6,-1.9 -6.3,-3.6c-10.4,-10.1 -20.6,-20.4 -30.9,-30.6c-1.3,-1.2 -2.6,-2.4 -4.9,-4.6c-12.5,12.5 -24.8,24.7 -37.4,37.3c0,-25.2 0,-50.4 0,-75.5c-24,0 -47.4,0 -71.3,0c0,25.9 0,51.5 0,77c-0.4,0.3 -0.8,0.5 -1.3,0.8c-13,-13.7 -26,-27.4 -39.9,-42c-2.6,3.1 -3.8,4.8 -5.3,6.3c-12.3,12.6 -24.6,25.3 -37.1,37.8c-1.8,1.8 -4.3,3.1 -6.7,3.8c-11,3.2 -22.1,6.1 -33.2,9.2c-5.1,1.4 -10.1,2.9 -15.4,4.4c4.6,17.1 9.1,33.8 14,51.6c-22.9,-13.2 -44.8,-25.8 -66.9,-38.6c-12,20.8 -23.8,41.2 -35.7,61.8c22.8,13.2 45,26 68.3,39.5c-19.6,5.5 -37.9,10.6 -56.4,15.8c5.2,18.7 10.1,36.9 15.3,54.9c1.5,5 1.5,9.6 0.1,14.6c-4.1,14.5 -7.8,29.2 -11.7,44.2c17.2,4.6 34,9 51.8,13.8C128.3,591.3 106.5,604 84.3,616.8zM694.6,265.9c-10,9 -19.8,17.8 -29.7,26.8c9.8,11 19.4,21.6 29.1,32.5c-11.3,0 -21.6,0 -33.5,0c0,7.8 -0.1,15.9 0,24c0.1,7.5 -1.4,14.3 -6.2,20.4c-3.9,4.9 -6.9,10.6 -10.6,16.2c8.2,5.3 16.3,10.6 25.3,16.5c-15,3.2 -28.6,6.1 -42.6,9.1c2.8,13.2 5.6,26.1 8.4,39.2c14.6,-3.1 28.4,-5.9 43.5,-9.1c-6.3,10 -11.9,18.8 -17.6,27.8c6.8,4.4 13.1,8.8 19.7,12.5c6.7,3.7 11.4,8.6 14.4,15.8c2.7,6.5 6.4,12.6 9.7,19c9,-4.6 17.4,-8.9 26.8,-13.7c-4.7,14.5 -8.9,27.8 -13.3,41.5c13,4.2 25.4,8.2 38.1,12.3c4.7,-14.3 9.1,-27.8 13.8,-42.2c5.3,10.1 10.2,19.5 15.4,29.2c9,-4.7 17.7,-9.3 26.5,-13.6c2.6,-1.2 5.6,-1.9 8.5,-2c9.3,-0.2 18.5,-0.1 28.3,-0.1c0.5,-8.7 1,-18.2 1.6,-28.9c10.2,11.3 19.6,21.7 29.2,32.2c10.2,-9.2 19.8,-17.9 29.7,-26.8c-9.9,-11 -19.4,-21.6 -29,-32.4c11.2,0 21.6,0 32.4,0c0.4,-9.3 0.6,-18.8 1.4,-28.2c0.3,-3.3 1.3,-6.8 3,-9.7c4.7,-8 9.9,-15.6 15,-23.5c-8.5,-5.5 -16.5,-10.7 -25.4,-16.5c14.7,-3.1 28.4,-6.1 42.6,-9.1c-2.8,-13.2 -5.6,-26.1 -8.3,-39.2c-14.6,3.1 -28.6,6 -43.5,9.1c6.3,-9.9 11.9,-18.7 17.7,-27.9c-9.6,-6.1 -19.1,-11.9 -28.3,-18.2c-2.6,-1.8 -5,-4.4 -6.6,-7.1c-4.1,-7.2 -7.7,-14.6 -11.5,-22.1c-8.9,4.5 -17.3,8.8 -26.9,13.8c4.7,-14.5 9,-27.8 13.4,-41.5c-12.8,-4.2 -25.3,-8.2 -38,-12.4c-4.6,13.9 -9,27.6 -13.8,42.2c-5.4,-10.3 -10.3,-19.6 -15.4,-29.2c-8.9,4.6 -17.1,9.3 -25.7,13.2c-3.7,1.7 -8.1,2.7 -12.2,2.8c-8.1,0.2 -16.1,-0.6 -24.4,-0.9c-0.5,10.1 -1.1,19.5 -1.6,30.1C713.5,286.8 704.2,276.6 694.6,265.9zM590.1,428.7c9.6,2.5 18.3,4.8 27.7,7.3c-1.5,-7.2 -2.9,-13.7 -4.4,-20.8C605.6,419.8 598.3,424 590.1,428.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M362.9,770.2c-10.5,0 -20.2,0 -30.5,0c0,-35.2 0,-70 0,-104.7c-19.4,19.1 -38.8,38.1 -58.2,57.1c-7.3,-7.5 -14.2,-14.6 -22.1,-22.7c5.1,-4.8 10.9,-9.8 16.3,-15.2c20.4,-20.4 40.7,-40.9 60.9,-61.4c1.6,-1.6 3,-4.2 3,-6.4c0.2,-27.2 0.1,-54.3 0.1,-81.5c0,-0.6 -0.1,-1.3 -0.3,-2.6c-1.9,1 -3.5,1.8 -5,2.6c-21.6,12.5 -43.1,25.1 -64.8,37.5c-3.8,2.2 -5.7,4.9 -6.7,9.1c-8.7,34.4 -17.6,68.7 -26.4,103c-0.3,1.1 -0.7,2.2 -1.3,3.8c-9.7,-2.5 -19.2,-4.9 -29.4,-7.5c7.1,-27.8 14.2,-55.2 21.6,-84.1c-31.6,18.2 -62,35.8 -92.8,53.5c-5.2,-8.9 -10,-17.4 -15.3,-26.4c30.5,-17.6 60.8,-35.1 92.1,-53.3c-27.2,-7.2 -53.3,-14.1 -80,-21.1c2.5,-9.7 5,-19.2 7.6,-29.1c1.9,0.4 3.6,0.6 5.3,1c33.6,8.8 67.3,17.7 100.9,26.4c1.8,0.5 4.2,0.8 5.6,-0.1c24,-13.7 47.9,-27.5 72.4,-41.6c-1.6,-1.1 -2.8,-1.9 -4,-2.6c-22.6,-13 -45.3,-26.1 -68,-38.9c-2,-1.1 -5.1,-1.2 -7.3,-0.6c-35,9.6 -69.9,19.3 -104.8,29c-0.8,0.2 -1.6,0.4 -3,0.8c-2.7,-9.7 -5.4,-19.2 -8.2,-29.3c27.7,-7.7 55.1,-15.4 83.6,-23.3c-31.5,-18.2 -61.9,-35.8 -92.7,-53.6c5.2,-9 10.2,-17.6 15.3,-26.5c30.6,17.7 60.8,35.1 92.2,53.2c-7.4,-27.2 -14.5,-53.2 -21.7,-79.8c9.8,-2.7 19.4,-5.3 29.4,-8.1c2.9,10.7 5.8,21.1 8.6,31.4c6.8,24.9 13.5,49.8 20.3,74.6c0.5,1.9 1.9,4.1 3.5,5c23.3,13.6 46.7,27 70,40.5c0.5,0.3 1.2,0.4 2.4,0.9c0,-2.3 0,-4 0,-5.8c0,-25.3 0,-50.7 -0.3,-76c0,-2.5 -1.3,-5.5 -3.1,-7.2c-25.2,-25 -50.6,-49.8 -75.9,-74.6c-1.3,-1.3 -2.8,-2.4 -4.8,-4.1c7.9,-7.3 15.2,-14 22.9,-21.1c19.7,19.3 39.9,39.1 61.1,59.9c0,-36.4 0,-71.4 0,-106.8c10.3,0 20.1,0 30.5,0c0,34.9 0,69.7 0,104.6c19.4,-19.4 38.5,-38.5 57.6,-57.5c7.8,7.9 14.8,15 22,22.4c-0.6,0.6 -1.6,1.9 -2.7,3c-24.5,24.7 -49.1,49.4 -73.6,74.2c-1.5,1.5 -2.9,3.9 -2.9,5.9c-0.2,28 -0.1,56 -0.1,84c0,0.5 0.2,1 0.3,1.8c0.8,-0.3 1.6,-0.5 2.3,-0.9c24.6,-14.2 49.3,-28.5 73.8,-42.9c1.8,-1.1 3.1,-3.7 3.7,-5.9c9,-34.4 17.9,-68.9 26.8,-103.4c0.4,-1.4 0.8,-2.9 1.4,-4.9c9.8,2.5 19.3,5 29.5,7.6c-7.2,28 -14.3,55.6 -21.6,84.1c31.4,-18.1 61.9,-35.7 92.8,-53.5c5.1,8.8 10.1,17.4 15.3,26.5c-30.6,17.7 -60.9,35.2 -92.2,53.3c27.3,7.2 53.4,14.1 80,21.1c-2.6,9.9 -5.1,19.5 -7.8,29.5c-15,-3.9 -29.6,-7.7 -44.2,-11.6c-20.6,-5.4 -41.2,-10.9 -61.8,-16.2c-2,-0.5 -4.8,-0.5 -6.5,0.5c-24,13.7 -47.9,27.5 -71.8,41.3c-0.7,0.4 -1.3,0.9 -2.4,1.7c1.9,1.2 3.3,2.2 4.9,3.1c22.1,12.7 44.1,25.4 66.3,37.9c2.3,1.3 5.7,1.7 8.3,1c35.8,-9.7 71.5,-19.7 107.9,-29.8c2.7,9.8 5.4,19.4 8.2,29.4c-27.7,7.7 -55,15.3 -83.6,23.3c31.4,18.2 61.9,35.8 92.7,53.6c-5.1,8.8 -10,17.4 -15.3,26.5c-30.6,-17.6 -60.9,-35.2 -92.2,-53.2c7.3,27 14.4,53.1 21.7,79.9c-9.8,2.7 -19.3,5.3 -29.4,8c-2.7,-9.8 -5.3,-19.2 -7.9,-28.6c-7,-25.7 -13.9,-51.4 -21.1,-77c-0.6,-2 -1.9,-4.4 -3.6,-5.5c-23.7,-13.9 -47.5,-27.6 -71.3,-41.3c-0.7,-0.4 -1.4,-0.6 -2.9,-1.3c0,1.8 0,3 0,4.3c0.1,26.2 0.1,52.3 0.4,78.5c0,2.3 1.3,5.1 3,6.8c25.9,25.7 52,51.2 78,76.8c0.6,0.6 1.4,0.9 1.9,1.1c-7.7,7.4 -14.8,14.3 -22.4,21.7c-19.2,-18.9 -39.5,-38.7 -60.7,-59.6C362.9,699.8 362.9,734.9 362.9,770.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M382.8,446.5c0,-14.9 0,-29.3 0.1,-43.7c0,-1.1 1,-2.4 1.9,-3.3c19.5,-19.7 39.1,-39.5 58.7,-59.2c0.3,-0.3 0.8,-0.5 1.9,-1.1c-3.2,12.4 -6.1,24.2 -9.2,36c-3.8,14.8 -7.6,29.6 -11.6,44.4c-0.5,1.9 -1.7,4.2 -3.2,5.1c-11.8,7.1 -23.8,13.9 -35.8,20.8C384.9,445.8 384.1,446 382.8,446.5zM399.6,417.9c10.4,-4.2 13.7,-9.9 14.3,-24.3c-3.4,3.4 -6.4,7 -10,9.8C399,407.2 398.2,412 399.6,417.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M539.2,506.6c-26.7,7.4 -52.9,14.8 -79.2,22c-1.4,0.4 -3.4,0.1 -4.7,-0.6c-11.1,-6.3 -22.2,-12.7 -33.3,-19.2c-0.4,-0.2 -0.6,-0.7 -1.1,-1.4c12.5,-7.2 24.8,-14.4 37.2,-21.4c1,-0.6 2.6,-0.6 3.7,-0.3c25.2,6.6 50.4,13.3 75.6,19.9C537.8,505.8 538.1,506 539.2,506.6zM475.8,506.9c-7.4,-2.8 -15,-6.7 -21.9,1C461.6,515.2 468.5,507.8 475.8,506.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M441.6,671.5c-4.9,-5.6 -9.6,-11.5 -14.9,-16.8c-13.4,-13.4 -27.1,-26.6 -40.6,-40c-1.1,-1.1 -2.5,-2.7 -2.5,-4c-0.2,-13.6 -0.1,-27.2 -0.1,-41.7c10.4,6 19.9,11.8 29.7,16.9c6.6,3.4 10,7.9 11.7,15.2c5.3,21.5 11.5,42.7 17.3,64c0.4,1.6 0.7,3.2 1.1,4.7C442.8,670.5 442.2,671 441.6,671.5zM411,615.7c-1.7,-13 -3.7,-16 -11.2,-17.3C397.6,608.1 406.8,610.3 411,615.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M311.8,567.9c0,14.8 0,28.4 -0.1,42c0,1.3 -0.7,3 -1.6,3.9c-17.9,18.1 -35.8,36.2 -53.8,54.2c-0.3,0.3 -0.8,0.5 -1.9,1c3.2,-12.7 6.3,-24.9 9.4,-37c3.3,-12.9 6.5,-25.8 10.1,-38.6c0.7,-2.5 2.8,-5.2 5.1,-6.6C289.5,580.5 300.3,574.6 311.8,567.9zM295,596.8c-9.2,2.7 -6.8,11.4 -9.2,17.5C291.1,609.7 298.2,606 295,596.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M311.4,444.4c-12.5,-7.2 -24.2,-13.9 -35.8,-20.7c-0.9,-0.5 -1.6,-1.7 -1.9,-2.7c-6.8,-24.8 -13.5,-49.6 -19.4,-75c5.8,5.6 11.5,11.1 17.2,16.7c12.6,12.4 25.1,24.7 37.6,37.2c1.1,1.1 2.1,2.7 2.2,4.1C311.5,417 311.4,430.2 311.4,444.4zM294.7,415.1c2.3,-8.8 -5.6,-10.7 -9.3,-15.3C287.3,405.5 285.7,413.3 294.7,415.1z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M275.7,506.3c-11.9,6.9 -22.9,13.3 -34.1,19.6c-1.4,0.8 -3.6,1.2 -5.1,0.8c-24.2,-6.2 -48.3,-12.6 -72.4,-19c-0.6,-0.2 -1.1,-0.6 -2.3,-1.2c17.5,-4.9 34.4,-9.6 51.3,-14.3c7.5,-2.1 15.1,-4.2 22.6,-6.2c1.5,-0.4 3.5,-0.6 4.6,0C252,492.5 263.4,499.2 275.7,506.3zM242.3,506.3c-6.2,-6.3 -11.8,-1.4 -17.5,0C230.5,507.5 236.3,512.4 242.3,506.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M690.8,475.1c-4.8,-3 -9.4,-6 -14.5,-9.2c8.6,-13.5 17,-26.8 26.1,-41.2c-20.2,4.3 -39.2,8.3 -58.8,12.4c-1.2,-5.6 -2.4,-11 -3.6,-16.9c19.4,-4.1 38.3,-8.2 58.4,-12.5c-13.5,-8.7 -26.2,-16.9 -39.1,-25.3c3.2,-5 6.3,-9.7 9.4,-14.6c16.7,10.8 33.2,21.3 49.4,32c3.2,2.1 6.2,2.6 9.8,1.7c13.6,-3.1 27.3,-5.9 41.7,-9c-1.9,-2.2 -3.5,-4.1 -5.1,-5.9c-8.4,-9.2 -16.7,-18.6 -25.3,-27.6c-1.5,-1.6 -4.2,-2.7 -6.3,-2.8c-19.1,-1 -38.3,-1.7 -57.4,-2.5c-1.1,0 -2.3,-0.3 -4.1,-0.5c0.3,-5.7 0.6,-11.2 0.8,-17c16.1,0.7 31.7,1.3 48.6,2c-13.9,-15.5 -27,-30.1 -40.2,-44.8c4.3,-3.8 8.3,-7.5 12.9,-11.6c13.1,14.5 26.1,28.9 40.1,44.4c0.8,-16.1 1.6,-30.9 2.3,-46.4c5.9,0.3 11.4,0.6 17.3,0.9c-0.8,16.7 -1.2,32.9 -2.6,48.9c-0.9,10 0.5,18.1 8.4,25.3c8.3,7.6 15.3,16.6 23.4,25.6c0.8,-2 1.4,-3.4 1.9,-4.9c3.9,-12.2 7.7,-24.4 11.8,-36.5c1.2,-3.5 0.7,-6.2 -0.9,-9.4c-9.3,-17.6 -18.5,-35.4 -28,-53.6c5.1,-2.7 10,-5.2 15.4,-8.1c7.5,14.4 14.8,28.3 22.6,43.2c6.3,-19.4 12.4,-38 18.7,-57.1c5.5,1.7 10.8,3.4 16.5,5.2c-6.1,18.7 -12.1,37.2 -18.4,56.9c14.3,-7.3 27.6,-14.1 41.3,-21.2c2.6,5.1 5.2,9.9 8,15.3c-7.9,4.1 -15.7,8.2 -23.4,12.2c-9.9,5.1 -19.9,10.1 -29.7,15.3c-1.8,0.9 -3.9,2.5 -4.5,4.2c-5,14.6 -9.7,29.3 -14.7,45c2.2,-0.3 3.7,-0.4 5.2,-0.7c13.7,-2.9 27.3,-5.7 40.9,-8.9c2.3,-0.5 4.8,-2.3 6.1,-4.3c11.1,-17 21.9,-34.2 33.2,-51.9c4.9,3.1 9.5,6 14.7,9.3c-8.6,13.6 -17,26.9 -26.1,41.2c20.1,-4.2 39.2,-8.3 58.8,-12.4c1.2,5.7 2.4,11 3.7,16.9c-19.3,4.1 -38.2,8.2 -58.4,12.5c13.6,8.8 26.2,16.9 39,25.3c-3.2,5 -6.1,9.5 -9.3,14.5c-4.5,-2.9 -8.7,-5.5 -12.8,-8.2c-12.6,-8.1 -25.1,-16.3 -37.8,-24.3c-1.9,-1.2 -4.7,-1.8 -6.8,-1.3c-14.9,2.9 -29.6,6.1 -45,9.4c0.8,1.2 1.3,2.1 2,2.9c9.3,10.3 18.4,20.6 27.9,30.6c1.6,1.7 4.4,2.9 6.8,3c19.1,1 38.2,1.8 57.4,2.6c1.1,0.1 2.2,0.3 3.4,0.5c0,5.5 0,10.8 0,16.9c-16.1,-0.7 -31.8,-1.3 -49,-2.1c13.8,15.4 26.8,29.9 40.2,44.8c-4.2,3.9 -8.3,7.6 -12.8,11.7c-13.2,-14.6 -26.2,-29.1 -40.1,-44.5c-0.8,15.9 -1.6,30.7 -2.3,45.6c-5.7,0 -11.2,0 -17.3,0c0.6,-12.7 1.2,-24.8 1.8,-37c0.4,-7.8 0.9,-15.6 1.2,-23.4c0.1,-1.6 0,-3.6 -1,-4.6c-10.4,-11.9 -21.1,-23.5 -32.3,-36c-3.3,10.3 -6.4,19.8 -9.5,29.4c-0.3,0.8 -0.3,1.7 -0.7,2.4c-5.8,10.5 -3.2,19.7 2.6,29.6c8.3,14 15.2,28.7 22.9,43.5c-5.2,2.7 -10,5.3 -15.3,8.1c-7.4,-14.1 -14.7,-28 -22.6,-43.2c-6.4,19.7 -12.5,38.2 -18.7,57.1c-5.5,-1.7 -10.7,-3.4 -16.5,-5.2c6.1,-18.7 12,-37.2 18.4,-56.9c-14.4,7.4 -27.6,14.2 -41.3,21.2c-2.7,-5.1 -5.2,-9.9 -8,-15.3c7.6,-3.9 15,-7.8 22.5,-11.7c10.3,-5.3 20.7,-10.6 31,-16c1.5,-0.8 3.4,-2 3.9,-3.5c5,-14.7 9.8,-29.6 14.9,-45.3c-10.9,2.3 -20.9,4.4 -30.9,6.6c-0.6,0.1 -1.3,0.6 -1.9,0.6c-11.8,-0.1 -18.1,6.9 -23.5,16.5c-7.4,13 -15.9,25.4 -24,38C692.7,472.4 691.8,473.6 690.8,475.1z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M815.9,372.4c2.6,-8.2 4.9,-15.3 7.3,-22.4c0.4,-1.2 1.7,-2.5 2.9,-3.1c13.2,-6.9 26.5,-13.7 39.8,-20.5c0.4,-0.2 0.9,-0.1 2.1,-0.2c-6.6,10.4 -13.4,20 -19,30.2c-4.3,8 -9.9,12.6 -19.1,13.3C825.6,369.9 821.3,371.3 815.9,372.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M825.3,411.5c8.6,-1.8 16.2,-3.5 23.8,-5c0.9,-0.2 2,0 2.8,0.5c12.3,7.8 24.5,15.7 36,23.1c-10.7,0 -22.1,-0.5 -33.4,0.2c-9.4,0.6 -16.2,-2.3 -21.4,-10.1C831.1,417.2 828.3,414.8 825.3,411.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M794.9,437.7c5.5,6.1 10.6,11.7 15.6,17.5c0.8,1 1.2,2.7 1.1,4.1c-0.6,14.1 -1.3,28.2 -2,43.8c-1.4,-2.4 -2.2,-3.6 -2.9,-4.9c-5.9,-11.3 -11.9,-22.6 -17.6,-34c-0.9,-1.8 -1.1,-4.5 -0.6,-6.4C790.3,451.1 792.6,444.7 794.9,437.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M708.8,468.3c7.7,-12.2 15.4,-24.4 23.3,-36.5c0.7,-1.1 2.2,-2.2 3.5,-2.5c6.8,-1.6 13.6,-2.9 21.3,-4.5c-2.6,7.9 -4.9,15.2 -7.3,22.5c-0.3,0.9 -1.4,1.8 -2.4,2.3c-12.5,6.5 -25,12.9 -37.5,19.4C709.3,468.8 709.1,468.5 708.8,468.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M764.9,295.9c6.9,13.2 13.4,25.6 19.8,38.2c0.5,1 0.5,2.6 0.2,3.7c-2,6.7 -4.2,13.3 -6.7,20.9c-5.5,-6.2 -10.7,-11.9 -15.7,-17.7c-0.4,-0.5 -0.4,-1.5 -0.4,-2.3c0.6,-13.3 1.2,-26.6 1.8,-39.8C763.9,298.1 764.4,297.4 764.9,295.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M748.3,385.5c-7.5,1.6 -13.8,3.1 -20.2,4.3c-1.5,0.3 -3.6,0.4 -4.8,-0.4c-11.8,-7.4 -23.4,-15 -34.9,-23.4c2,0 4.1,-0.1 6.1,0c11.5,0.5 22.9,0.9 34.4,1.5c1.4,0.1 3.2,0.3 4.1,1.2C738.1,374 742.8,379.5 748.3,385.5z"/>
+</vector>
diff --git a/res/drawable/icon_stamp.xml b/res/drawable/icon_stamp.xml
new file mode 100644
index 0000000..79456e4
--- /dev/null
+++ b/res/drawable/icon_stamp.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,119.2c-108.3,0-216.5,0-324.7-0.1c0,3.6,0,7.1,0,10.6c108.3,0,216.5,0,324.7,0.1
+							C342.7,126.3,342.7,122.8,342.7,119.2 M288.7,110.8C270.3,78.2,226.9,43.5,168,49.2c-26.8,2.6-50.3,13.1-70.6,30.9
+							c-10.1,8.8-18.5,19.1-25.4,30.8c3,0,5.8,0,8.5,0c0.9,0,1.5-0.3,2-1c11.4-17.1,26.1-30.5,44.3-39.8
+							c23.8-12.2,48.8-15.9,75-11.1c24,4.4,44.6,15.6,62,32.9c5.6,5.6,10.5,11.7,14.8,18.3c0.4,0.6,0.9,0.9,1.6,0.8
+							c2.5,0,5.1,0,7.6,0C288,110.9,288.3,110.9,288.7,110.8 M317.3,136.3c-91.3,0-182.6,0-273.9-0.1c0,2.6,0,5,0,7.5
+							c91.3,0,182.6,0,273.9,0.1C317.3,141.3,317.3,138.8,317.3,136.3 M268.9,110.9C249.2,83.2,212.1,60.6,167,66.1
+							c-15,1.8-29.1,6.7-42.1,14.4c-13,7.8-24,17.8-33.1,30.3c3.5,0,6.8,0,10.1,0c0.3,0,0.7-0.3,0.9-0.6c2.5-2.7,4.9-5.5,7.5-8
+							c15.9-15.2,34.7-24.5,56.4-27.6c12.4-1.7,24.7-1.2,36.8,1.8c21,5,38.6,15.8,52.9,32.1c1.6,1.8,3.1,2.6,5.4,2.4
+							C264.1,110.7,266.4,110.9,268.9,110.9 M171.5,111.3c0.6-0.3,0.9-0.4,1.3-0.6c2.5-1.3,5.1-2.7,7.6-4c0.7-0.4,1.2-0.3,1.8,0
+							c2.5,1.4,5.1,2.7,7.6,4.1c0.3,0.2,0.7,0.3,1.1,0.5c0-0.4,0-0.6-0.1-0.8c-0.5-3.1-1.1-6.2-1.6-9.3c-0.1-0.4,0.1-1,0.4-1.3
+							c1.7-1.8,3.5-3.5,5.3-5.2c0.6-0.6,1.3-1.2,2.1-2c-0.5-0.1-0.7-0.2-0.9-0.2c-2.9-0.4-5.8-0.9-8.8-1.3c-0.8-0.1-1.4-0.4-1.8-1.2
+							c-1.2-2.7-2.6-5.4-3.9-8c-0.1-0.2-0.3-0.5-0.5-0.8c-1.3,2.6-2.7,5-3.6,7.5c-0.8,2-2,2.6-3.9,2.8c-2.7,0.2-5.3,0.7-8.1,1.2
+							c0.2,0.2,0.3,0.4,0.5,0.5c2.2,2.2,4.5,4.5,6.7,6.7c0.4,0.4,0.6,0.8,0.5,1.4c-0.3,1.1-0.4,2.3-0.6,3.4
+							C172.3,106.8,171.9,108.9,171.5,111.3 M134.3,96.1c1.8,1.9,3.5,3.7,5.2,5.5c0.5,0.5,0.6,1,0.5,1.7c-0.4,2.4-0.8,4.9-1.3,7.5
+							c0.5-0.2,0.8-0.4,1.1-0.5c1.9-1,3.8-2,5.7-3.1c0.6-0.3,1-0.4,1.6,0c1.9,1.1,3.9,2.1,5.8,3.1c0.3,0.2,0.6,0.3,1,0.5
+							c-0.5-2.6-0.9-5.1-1.3-7.5c-0.1-0.7,0-1.1,0.5-1.7c1.8-1.8,3.5-3.7,5.2-5.5c-0.2,0-0.5-0.1-0.8-0.2c-2.2-0.3-4.4-0.7-6.6-1
+							c-0.7-0.1-1-0.4-1.2-0.9c-1-2.1-2-4.2-3-6.2c-0.1-0.2-0.3-0.4-0.4-0.7c-1.2,2.4-2.3,4.7-3.4,7c-0.2,0.5-0.5,0.8-1.1,0.9
+							C139.3,95.4,136.7,95.8,134.3,96.1 M216.1,87.1c-1.2,2.5-2.4,4.8-3.5,7.1c-0.3,0.5-0.5,0.8-1.2,0.9c-1.3,0.1-2.7,0.4-4,0.6
+							c-1.2,0.2-2.4,0.4-3.5,0.5c1.7,1.8,3.4,3.7,5.2,5.5c0.5,0.5,0.6,1,0.5,1.8c-0.4,2.4-0.8,4.9-1.3,7.5c0.5-0.2,0.8-0.4,1.1-0.5
+							c1.9-1,3.9-2,5.8-3.1c0.5-0.3,0.9-0.3,1.4,0c2,1.1,3.9,2.1,5.9,3.2c0.3,0.2,0.6,0.3,1,0.5c-0.4-2.6-0.8-5-1.3-7.4
+							c-0.1-0.8,0-1.3,0.6-1.8c1.8-1.8,3.5-3.6,5.2-5.4c-2.2-0.3-4.4-0.7-6.7-1c-1.1-0.1-1.8-0.5-2.3-1.6
+							C218.3,91.4,217.2,89.4,216.1,87.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,119.2c0,3.6,0,7.1,0,10.6c-108.2,0-216.4,0-324.7-0.1c0-3.5,0-7.1,0-10.6
+							C126.3,119.1,234.5,119.2,342.7,119.2"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M288.7,110.8c-0.4,0-0.7,0.1-1,0.1c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2-0.2-1.6-0.8
+							c-4.3-6.6-9.3-12.7-14.8-18.3c-17.4-17.3-38-28.5-62-32.9c-26.2-4.8-51.3-1.1-75,11.1c-18.2,9.3-32.9,22.7-44.3,39.8
+							c-0.5,0.8-1.1,1.1-2,1c-2.7-0.1-5.5,0-8.5,0c7-11.7,15.4-22,25.4-30.8c20.3-17.8,43.9-28.3,70.6-30.9
+							C226.9,43.5,270.3,78.2,288.7,110.8"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M317.3,136.3c0,2.5,0,5,0,7.5c-91.3,0-182.6,0-273.9-0.1c0-2.5,0-5,0-7.5
+			C134.7,136.3,226,136.3,317.3,136.3"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.9,110.9c-2.5,0-4.8-0.2-7.1,0c-2.3,0.2-3.8-0.6-5.4-2.4c-14.3-16.3-31.9-27.1-52.9-32.1
+			c-12.1-2.9-24.4-3.5-36.8-1.8c-21.7,3.1-40.5,12.3-56.4,27.6c-2.6,2.5-5,5.4-7.5,8c-0.3,0.3-0.6,0.6-0.9,0.6c-3.3,0-6.5,0-10.1,0
+			c9.1-12.5,20.1-22.6,33.1-30.3c13-7.8,27.1-12.6,42.1-14.4C212.1,60.6,249.2,83.2,268.9,110.9"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M171.5,111.3c0.4-2.4,0.7-4.5,1.1-6.7c0.2-1.1,0.3-2.3,0.6-3.4c0.1-0.6,0-1-0.5-1.4
+			c-2.3-2.2-4.5-4.5-6.7-6.7c-0.1-0.1-0.3-0.3-0.5-0.5c2.8-0.4,5.4-0.9,8.1-1.2c2-0.2,3.2-0.8,3.9-2.8c1-2.6,2.4-4.9,3.6-7.5
+			c0.2,0.3,0.4,0.6,0.5,0.8c1.3,2.7,2.7,5.3,3.9,8c0.4,0.8,0.9,1.1,1.8,1.2c2.9,0.4,5.8,0.8,8.8,1.3c0.2,0,0.4,0.1,0.9,0.2
+			c-0.8,0.7-1.4,1.4-2.1,2c-1.8,1.7-3.5,3.5-5.3,5.2c-0.3,0.3-0.5,0.9-0.4,1.3c0.5,3.1,1,6.2,1.6,9.3c0,0.2,0,0.4,0.1,0.8
+			c-0.4-0.2-0.8-0.3-1.1-0.5c-2.6-1.4-5.1-2.7-7.6-4.1c-0.6-0.4-1.1-0.4-1.8,0c-2.5,1.4-5,2.7-7.6,4
+			C172.4,110.8,172.1,111,171.5,111.3"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M134.3,96.1c2.5-0.4,5-0.8,7.5-1.1c0.6-0.1,0.9-0.4,1.1-0.9c1.1-2.3,2.2-4.6,3.4-7
+			c0.2,0.3,0.3,0.5,0.4,0.7c1,2.1,2,4.2,3,6.2c0.3,0.5,0.6,0.9,1.2,0.9c2.2,0.3,4.4,0.6,6.6,1c0.3,0,0.6,0.1,0.8,0.2
+			c-1.7,1.8-3.5,3.7-5.2,5.5c-0.5,0.5-0.6,1-0.5,1.7c0.4,2.4,0.8,4.9,1.3,7.5c-0.4-0.2-0.8-0.3-1-0.5c-1.9-1-3.9-2-5.8-3.1
+			c-0.6-0.3-1-0.3-1.6,0c-1.9,1.1-3.8,2-5.7,3.1c-0.3,0.2-0.6,0.3-1.1,0.5c0.4-2.6,0.8-5.1,1.3-7.5c0.1-0.7,0-1.2-0.5-1.7
+			C137.7,99.8,136,98,134.3,96.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M216.1,87.1c1.1,2.3,2.2,4.4,3.1,6.5c0.5,1.1,1.2,1.5,2.3,1.6c2.3,0.3,4.5,0.6,6.7,1
+			c-1.7,1.8-3.4,3.7-5.2,5.4c-0.6,0.6-0.7,1.1-0.6,1.8c0.5,2.4,0.8,4.8,1.3,7.4c-0.4-0.2-0.7-0.3-1-0.5c-2-1-4-2.1-5.9-3.2
+			c-0.5-0.3-0.9-0.3-1.4,0c-1.9,1.1-3.9,2.1-5.8,3.1c-0.3,0.2-0.6,0.3-1.1,0.5c0.4-2.6,0.8-5.1,1.3-7.5c0.1-0.7,0-1.2-0.5-1.8
+			c-1.8-1.8-3.5-3.6-5.2-5.5c1.1-0.2,2.3-0.4,3.5-0.5c1.3-0.2,2.7-0.4,4-0.6c0.6-0.1,0.9-0.3,1.2-0.9
+			C213.7,91.9,214.8,89.6,216.1,87.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,234.5c-108.2,0-216.4,0-324.7-0.1c0,3.5,0,7.1,0,10.6c108.2,0,216.4,0,324.7,0.1
+			C342.7,241.6,342.7,238.1,342.7,234.5 M287.7,253.4c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2,0.2-1.6,0.8c-4.3,6.6-9.3,12.7-14.8,18.3
+			c-17.4,17.3-38,28.5-62,32.9c-26.2,4.8-51.3,1.1-75-11.1c-18.2-9.4-32.9-22.7-44.3-39.9c-0.5-0.8-1.1-1.1-2-1
+			c-2.7,0.1-5.5,0-8.5,0c7,11.7,15.4,22,25.4,30.8c20.3,17.8,43.9,28.3,70.6,30.9c58.9,5.7,102.3-29,120.7-61.6
+			C288.3,253.5,288,253.4,287.7,253.4 M317.3,220.5c-91.3,0-182.6,0-273.9-0.1c0,2.5,0,5,0,7.5c91.3,0,182.6,0,273.9,0.1
+			C317.3,225.5,317.3,223,317.3,220.5 M261.7,253.4c-2.3-0.2-3.8,0.6-5.4,2.4c-14.3,16.3-31.9,27.1-52.9,32.1
+			c-12.1,2.9-24.4,3.5-36.8,1.7c-21.7-3.1-40.5-12.4-56.4-27.6c-2.6-2.5-5-5.4-7.5-8c-0.3-0.3-0.6-0.6-0.9-0.6c-3.3,0-6.5,0-10.1,0
+			c9.1,12.5,20.1,22.6,33.1,30.3c13,7.8,27.1,12.6,42.1,14.5c45.1,5.5,82.2-17.1,101.9-44.8C266.4,253.4,264,253.6,261.7,253.4
+			 M172.6,259.7c0.2,1.1,0.3,2.3,0.6,3.4c0.1,0.6,0,1-0.5,1.4c-2.3,2.2-4.5,4.5-6.8,6.7c-0.1,0.1-0.3,0.3-0.5,0.5
+			c2.8,0.4,5.4,0.9,8.1,1.2c2,0.2,3.2,0.8,3.9,2.8c1,2.6,2.4,4.9,3.6,7.5c0.2-0.3,0.4-0.6,0.5-0.8c1.3-2.7,2.7-5.3,3.9-8
+			c0.4-0.8,0.9-1.1,1.8-1.2c2.9-0.4,5.8-0.8,8.8-1.3c0.2,0,0.4-0.1,0.9-0.2c-0.8-0.7-1.4-1.4-2.1-2c-1.8-1.7-3.5-3.5-5.3-5.2
+			c-0.3-0.3-0.5-0.9-0.4-1.3c0.5-3.1,1-6.2,1.6-9.3c0-0.2,0-0.4,0.1-0.8c-0.4,0.2-0.8,0.3-1.1,0.5c-2.6,1.4-5.1,2.7-7.6,4.1
+			c-0.6,0.4-1.1,0.4-1.8,0c-2.5-1.4-5-2.7-7.5-4c-0.3-0.2-0.7-0.3-1.3-0.6C171.9,255.4,172.2,257.5,172.6,259.7 M141.8,269.2
+			c0.6,0.1,0.9,0.4,1.1,0.9c1.1,2.3,2.2,4.6,3.4,7c0.2-0.3,0.3-0.5,0.4-0.7c1-2.1,2-4.2,3-6.2c0.3-0.5,0.6-0.9,1.2-0.9
+			c2.2-0.3,4.4-0.6,6.6-1c0.3,0,0.6-0.1,0.8-0.2c-1.7-1.8-3.5-3.7-5.2-5.5c-0.5-0.5-0.6-1-0.5-1.7c0.4-2.4,0.9-4.9,1.3-7.5
+			c-0.4,0.2-0.7,0.3-1,0.5c-1.9,1-3.9,2-5.8,3.1c-0.6,0.3-1,0.3-1.6,0c-1.9-1.1-3.8-2.1-5.7-3.1c-0.3-0.2-0.6-0.3-1.1-0.5
+			c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.7c-1.8,1.8-3.5,3.6-5.2,5.5C136.7,268.5,139.2,268.9,141.8,269.2 M219.2,270.7
+			c0.5-1.1,1.2-1.5,2.3-1.6c2.3-0.3,4.5-0.6,6.7-1c-1.7-1.8-3.4-3.7-5.2-5.4c-0.6-0.6-0.7-1.1-0.6-1.8c0.5-2.4,0.8-4.8,1.3-7.4
+			c-0.4,0.2-0.7,0.3-1,0.5c-2,1-4,2.1-5.9,3.2c-0.5,0.3-0.9,0.3-1.4,0c-1.9-1.1-3.9-2.1-5.8-3.1c-0.3-0.2-0.6-0.3-1.1-0.5
+			c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.8c-1.8,1.8-3.5,3.6-5.2,5.5c1.1,0.2,2.3,0.4,3.5,0.5c1.3,0.2,2.7,0.4,4,0.6
+			c0.6,0.1,0.9,0.3,1.2,0.9c1.1,2.3,2.2,4.6,3.5,7.1C217.1,274.9,218.3,272.9,219.2,270.7"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M342.7,245.2c0-3.6,0-7.1,0-10.6c-108.2,0-216.4,0-324.7-0.1c0,3.5,0,7.1,0,10.6
+			C126.2,245.1,234.4,245.1,342.7,245.2"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M288.6,253.5c-0.4,0-0.7-0.1-1-0.1c-2.5,0-5.1,0-7.6,0c-0.7,0-1.2,0.2-1.6,0.8
+			c-4.3,6.6-9.3,12.7-14.8,18.3c-17.4,17.3-38,28.5-62,32.9c-26.2,4.8-51.3,1.1-75-11.1c-18.2-9.4-32.9-22.7-44.3-39.9
+			c-0.5-0.8-1.1-1.1-2-1.1c-2.7,0.1-5.5,0-8.5,0c7,11.7,15.4,22,25.4,30.8c20.3,17.8,43.9,28.3,70.6,30.9
+			C226.8,320.8,270.2,286.1,288.6,253.5"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M317.3,228c0-2.5,0-5,0-7.5c-91.3,0-182.6,0-273.9-0.1c0,2.5,0,5,0,7.5C134.7,228,226,228,317.3,228"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.8,253.4c-2.5,0-4.8,0.2-7.1,0c-2.3-0.2-3.8,0.6-5.4,2.4c-14.3,16.3-31.9,27.1-52.9,32.1
+			c-12.1,2.9-24.4,3.5-36.8,1.7c-21.7-3.1-40.5-12.4-56.4-27.6c-2.6-2.5-5-5.4-7.5-8c-0.3-0.3-0.6-0.6-0.9-0.6c-3.3,0-6.5,0-10.1,0
+			c9.1,12.5,20.1,22.6,33.1,30.3c13,7.8,27.1,12.6,42.1,14.5C212.1,303.6,249.2,281.1,268.8,253.4"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M171.5,253c0.4,2.4,0.7,4.5,1.1,6.7c0.2,1.1,0.3,2.3,0.6,3.4c0.1,0.6,0,1-0.5,1.4
+			c-2.3,2.2-4.5,4.5-6.7,6.7c-0.1,0.1-0.3,0.3-0.5,0.5c2.8,0.4,5.4,0.9,8.1,1.2c2,0.2,3.2,0.8,3.9,2.8c1,2.6,2.4,4.9,3.6,7.5
+			c0.2-0.3,0.4-0.6,0.5-0.8c1.3-2.7,2.7-5.3,3.9-8c0.4-0.8,0.9-1.1,1.8-1.2c2.9-0.4,5.8-0.8,8.8-1.3c0.2,0,0.4-0.1,0.9-0.2
+			c-0.8-0.7-1.4-1.4-2.1-2c-1.8-1.7-3.5-3.5-5.3-5.2c-0.3-0.3-0.5-0.9-0.4-1.3c0.5-3.1,1-6.2,1.6-9.3c0-0.2,0-0.4,0.1-0.8
+			c-0.4,0.2-0.8,0.3-1.1,0.5c-2.6,1.4-5.1,2.7-7.6,4.1c-0.6,0.4-1.1,0.4-1.8,0c-2.5-1.4-5-2.7-7.6-4
+			C172.4,253.4,172.1,253.3,171.5,253"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M134.2,268.1c2.5,0.4,5,0.8,7.5,1.1c0.6,0.1,0.9,0.4,1.1,0.9c1.1,2.3,2.2,4.6,3.4,7
+			c0.2-0.3,0.3-0.5,0.4-0.7c1-2.1,2-4.2,3-6.2c0.3-0.5,0.6-0.9,1.2-0.9c2.2-0.3,4.4-0.6,6.6-1c0.3,0,0.6-0.1,0.8-0.2
+			c-1.7-1.8-3.5-3.7-5.2-5.5c-0.5-0.5-0.6-1-0.5-1.7c0.4-2.4,0.9-4.9,1.3-7.5c-0.4,0.2-0.8,0.3-1,0.5c-1.9,1-3.9,2-5.8,3.1
+			c-0.6,0.3-1,0.3-1.6,0c-1.9-1.1-3.8-2-5.7-3.1c-0.3-0.2-0.6-0.3-1.1-0.5c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.7
+			C137.7,264.4,136,266.3,134.2,268.1"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M216,277.2c1.1-2.3,2.2-4.4,3.1-6.5c0.5-1.1,1.2-1.5,2.3-1.6c2.3-0.3,4.5-0.6,6.7-1
+			c-1.7-1.8-3.4-3.7-5.2-5.4c-0.6-0.6-0.7-1.1-0.6-1.8c0.5-2.4,0.8-4.8,1.3-7.4c-0.4,0.2-0.7,0.3-1,0.5c-2,1-4,2.1-5.9,3.2
+			c-0.5,0.3-0.9,0.3-1.4,0c-1.9-1.1-3.9-2.1-5.8-3.1c-0.3-0.2-0.6-0.3-1.1-0.5c0.4,2.6,0.8,5.1,1.3,7.5c0.1,0.7,0,1.2-0.5,1.8
+			c-1.8,1.8-3.5,3.6-5.2,5.5c1.1,0.2,2.3,0.4,3.5,0.5c1.3,0.2,2.7,0.4,4,0.6c0.6,0.1,0.9,0.3,1.2,0.9
+			C213.7,272.4,214.8,274.7,216,277.2"/>
+</vector>
diff --git a/res/drawable/icon_sun.xml b/res/drawable/icon_sun.xml
new file mode 100644
index 0000000..a76f406
--- /dev/null
+++ b/res/drawable/icon_sun.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="1008.0"
+    android:viewportWidth="1008.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M160.4,465.7c-6.2,-8.6 -5.7,-18.2 -6.4,-27.4c-0.8,-10.3 -1.6,-20.6 -1.8,-30.9c-0.2,-12.9 5.6,-22.6 18.1,-27.1c17.7,-6.4 35.5,-12.3 53.4,-18.1c4.1,-1.3 6.6,-3.2 8.6,-7.1c4.7,-9.4 9.6,-18.6 15.1,-27.5c2.4,-3.8 2.3,-6.6 0.5,-10.4c-20.1,-42.6 -40,-85.2 -60,-127.9c-0.5,-1.1 -1,-2.3 -1.9,-4.4c12.1,4.7 23.4,9.1 34.6,13.6c34.7,13.6 69.4,27.2 104,41c3.1,1.2 5.3,1 8.1,-0.9c39.1,-26.5 82.3,-42.6 129.2,-48.4c3.6,-0.4 4.7,-2.7 5.9,-5.1c20.1,-38.7 40.2,-77.3 60.4,-116c1,-2 2.2,-4 3.7,-6.8c3.3,9.5 6.2,18.1 9.1,26.8c11.8,34.8 23.6,69.6 35.3,104.5c1.3,3.8 3.1,5.8 7.2,7c41.1,12.4 77.8,32.8 109.9,61.3c2.9,2.6 5.5,3.4 9.3,2.4c47.7,-11.6 95.4,-23 143.1,-34.5c1.5,-0.4 3.1,-0.6 5.8,-1.2c-5.7,9 -10.7,17 -15.8,24.9c-11.1,17.4 -22.2,34.8 -33.4,52.2c-1.7,2.6 -1.9,4.7 -1.2,7.8c3.6,15.4 7,30.8 10.1,46.3c0.5,2.6 -0.1,5.6 -0.7,8.4c-6,26.8 -12.4,53.5 -18.1,80.3c-1.1,5.1 -0.2,10.6 0.2,15.9c0.1,1.4 2.1,2.9 3.5,3.9c28.7,19.9 57.5,39.8 86.3,59.7c11.9,8.2 23.9,16.3 36.7,25.2c-2.9,0.8 -4.9,1.4 -6.9,2c-43,11.6 -86,23.4 -129.1,34.7c-8.3,2.2 -13,6.2 -16.3,14.4c-8.4,20.6 -20.3,39.3 -33.5,57.1c-1.3,1.7 -2.1,4.7 -1.6,6.7c7.1,30.8 14.3,61.6 21.7,92.3c4.5,18.9 9.4,37.8 14,56.7c0.2,0.9 0.3,1.9 0.7,3.8c-9.8,-5.1 -18.9,-9.8 -28,-14.4c-33.8,-17.3 -67.6,-34.4 -101.3,-51.8c-8.4,-4.3 -15.5,-4.5 -24.6,-0.7c-15.8,6.7 -32.6,11.2 -49.1,16.3c-3.7,1.1 -6.6,2.4 -8.6,6c-13.4,24 -27,47.8 -40.4,71.8c-10.3,18.6 -20.4,37.4 -31,57.1c-1.2,-2.6 -2.2,-4.4 -3,-6.3c-16.6,-36.5 -33.6,-72.8 -49.7,-109.5c-6.2,-14.1 -14.1,-23.5 -30.3,-27.8c-16.3,-4.3 -31.5,-13.2 -47,-20.5c-3.7,-1.7 -6.7,-2.2 -10.3,-0.7c-23,9.8 -46,19.4 -68.9,29.2c-21.9,9.4 -43.7,18.9 -65.5,28.4c-1.2,0.5 -2.5,0.9 -4.7,1.8c0.9,-2.7 1.5,-4.7 2.2,-6.6c15.2,-45.1 30.4,-90.1 45.8,-135.2c1.6,-4.7 1.1,-8.3 -1.8,-12.4c-16.3,-24.2 -28.4,-50.4 -36.6,-78.4c-1.1,-3.8 -3,-5.8 -6.6,-7.1c-42.5,-15.5 -85,-31.1 -127.4,-46.6c-1.5,-0.6 -3,-1.1 -5.5,-2.1C104.3,495.8 132,480.9 160.4,465.7zM264.6,597.6C309.2,692 422.2,764 550.4,737.8c122.5,-25 194.8,-128.4 204.8,-218.1c-3.7,3 -7.2,6 -10.9,8.8c-15.3,11.5 -33,16.7 -51.6,19.8c-29.6,5 -59.3,9 -89.4,4.5c-27.6,-4.1 -51.4,-15.2 -67.2,-39.3c-5.5,-8.3 -10,-17.3 -14.9,-26c-8.9,-16 -17.7,-32 -26.7,-47.9c-1.7,-3 -4.4,-5.5 -7.6,-9.4c-2,5 -4,8.5 -4.9,12.3c-3.9,16.7 -7.1,33.5 -11.1,50.1c-3.4,14.2 -6,28.8 -11.6,42.2c-9.5,23 -28.5,37.1 -50.7,47.1c-23.6,10.7 -48.7,15.7 -74.2,19c-15.2,2 -30.4,4.6 -45.7,2C280.6,601.5 272.6,599.4 264.6,597.6zM274,351.1c2,-0.1 3.5,-0.2 5,-0.3c22.4,-1.5 44.8,-4.1 67.2,-4.4c36.5,-0.3 72.9,1 109.4,1.3c8.3,0.1 16.9,-0.1 24.8,-2.3c29.5,-8.2 58.8,-16.8 87.9,-26.3c25.5,-8.3 50.9,-16.5 77.3,-21.5c9.7,-1.8 19.4,-3.4 29.4,-5.1C556.9,180 358,206.2 274,351.1zM393.6,377.7c0,-0.2 0,-0.4 0,-0.5c-5,0 -10,0.3 -15,0c-29.3,-1.8 -58.6,-1.4 -87.8,2.1c-36.2,4.4 -71.2,13.6 -105.2,26.8c-3.1,1.2 -4,2.9 -3.8,5.9c0.6,7.1 0.8,14.3 1.4,21.4c0.7,8.1 1.6,15.8 6,23.3c11.5,19.1 21.6,39 33.2,58.1c7,11.6 14.7,23.1 23.7,33.2c16.5,18.4 37.6,28.1 62.8,25.7c14.4,-1.3 28.8,-3.4 43,-5.9c19.7,-3.5 38.9,-8.9 56.3,-19.5c15.3,-9.3 25.2,-22.4 28.8,-40.1c3.2,-16 6.2,-32 10,-47.8c3.4,-13.7 6.7,-27.5 12.1,-40.5c8.7,-21.1 36.9,-24.5 50.9,-8c7.2,8.4 13.4,17.8 19,27.4c10.2,17.6 19.4,35.6 29.2,53.5c7.1,13 17.9,22.2 32.1,26.1c10.8,3 22.1,5.2 33.3,5.8c25.6,1.4 50.8,-2.9 75.8,-8.1c20.1,-4.2 35.9,-15.3 46.3,-32.9c5.8,-9.8 11.3,-20.3 14.2,-31.2c7.2,-26.8 13,-54 19.2,-81.1c1,-4.2 2.5,-8.7 1.8,-12.7c-2,-11.6 -4.8,-23.1 -7.6,-34.6c-0.3,-1.3 -2.5,-3.1 -4,-3.1c-12.6,-0.9 -25.3,-1.9 -37.9,-1.9c-37,0 -73.5,4.3 -109,14.6c-31.9,9.2 -63.7,19.2 -95.2,29.8c-31.1,10.5 -62.7,16 -95.6,14.2C418.9,377.2 406.2,377.7 393.6,377.7zM726.3,767.5c-6.4,-26 -12.6,-50.8 -18.6,-75.1c-16.7,13.4 -33.2,26.7 -49.7,39.9C680.2,743.7 702.7,755.4 726.3,767.5zM487.2,842c12,-22.1 23.6,-43.3 34.7,-63.9c-21.6,-0.6 -43.1,-1.2 -64.6,-1.8C467,797.7 476.9,819.5 487.2,842zM320.1,719.6c-14.8,-13.7 -29.3,-27.1 -43.9,-40.5c-7.7,22.7 -15.5,45.7 -23.7,69.8C276,738.7 298.1,729.1 320.1,719.6zM793.7,501.1c-3.3,19.9 -6.5,39.3 -9.7,59.2c22.6,-6 45.4,-12.1 69.2,-18.5C832.7,527.8 813.2,514.4 793.7,501.1zM302.5,260.9c-20,-7.8 -40.1,-15.8 -61.5,-24.2c9.7,20.7 18.8,40 27.8,59.2C280.2,284.1 291.2,272.6 302.5,260.9zM526.4,133.2c-9.7,18.6 -18.9,36.3 -28,53.9c16.2,1.3 31.6,2.5 47.6,3.8C539.5,172 533.1,153.2 526.4,133.2zM193.6,524.3c-6.9,-12.2 -12.9,-23 -19.2,-34.2c-10.1,5.4 -19.7,10.6 -30.2,16.2C160.9,512.4 176.5,518.1 193.6,524.3zM721.3,288.6c19.2,1.1 36.9,2.1 54.6,3c0.9,0 2.2,-0.2 2.6,-0.8c4,-5.9 7.8,-12 12.2,-19C767.1,277.5 744.9,282.9 721.3,288.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M598.6,587.3c10.3,12.3 20.3,24.3 31,37.2c-8.6,4 -16.4,8.2 -24.7,11.5c-36.8,14.7 -75.1,18.4 -114.3,15.6c-32.6,-2.4 -64,-10 -93.7,-24.1c-2.1,-1 -4.2,-2 -6.2,-3.2c-4.6,-2.5 -6.2,-5.8 -4.4,-9.7c1.9,-4.3 5.2,-4.8 9.6,-3.8c12.2,2.8 24.3,6 36.6,7.6c51.3,6.8 101.3,2.8 148.5,-20.7c3,-1.5 5.9,-3.2 8.7,-4.9C592.6,591.2 595.4,589.3 598.6,587.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M463.5,392.2c-23.8,20.1 -26.6,48 -32.5,74.5c-2.7,12 -5.4,24 -7.4,36.2c-3.2,19 -15,30.5 -31.7,38.2c-19.9,9.1 -41.2,13.1 -62.6,15.9c-9.6,1.2 -19.2,2.7 -28.8,2.5c-21.2,-0.5 -37.1,-11.7 -49.6,-27.9c-6.3,-8.1 -11.7,-17 -16.9,-25.9c-9.2,-15.6 -17.3,-31.9 -26.9,-47.3c-6.4,-10.3 -9.6,-21 -9.7,-32.9c-0.1,-9.9 -1.7,-7.5 7,-10.7c41.6,-15.3 84.7,-23.4 129,-23.7c31.3,-0.2 62.6,0.8 93.9,1.1C438.7,392.3 450.4,392.2 463.5,392.2zM443.6,400.7c-2.9,0 -4.9,0 -6.9,0c-18.1,-0.2 -36.3,0.1 -54.4,-0.7c-34.5,-1.6 -68.9,-1.6 -103.1,4c-23.9,3.9 -47.2,9.6 -69.9,17.9c-1.4,0.5 -3.6,1.9 -3.5,2.7c0.9,6.8 0.6,14.4 3.6,20.2c10.2,19.8 21.4,39.1 32.7,58.3c5.4,9.1 11.2,18.2 18,26.3c12.7,15.3 28.9,24 49.5,21.4c15.7,-2 31.5,-3.7 46.8,-7.3c12.8,-3 25.4,-7.8 37.4,-13.3c11.8,-5.3 19.2,-15 21.4,-28.3c1,-6.2 2.6,-12.4 4,-18.5C425.3,455.7 427.8,426.8 443.6,400.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M498.8,386.9c12.3,-3.6 23.4,-6.8 34.4,-10.2c30.9,-9.6 61.6,-20.1 92.8,-28.9c42.6,-12.1 86.3,-16 130.5,-13.1c3.5,0.2 5.3,1.2 5.9,5c0.9,6.2 2.5,12.4 3.8,18.6c0.3,1.3 0.5,2.7 0.2,3.9c-6.6,28.5 -13,57.1 -20,85.5c-2.9,11.7 -8.1,22.5 -15.4,32.2c-9.6,12.6 -22,20.4 -37.7,23.4c-25.2,4.8 -50.6,8.8 -76.3,6.7c-7.4,-0.6 -14.8,-2.2 -21.9,-4.3c-10.9,-3.3 -19.3,-10.3 -24.8,-20.5c-10.1,-18.7 -20.1,-37.5 -30.6,-56.1c-4.1,-7.2 -8.9,-14 -13.8,-20.8c-5.7,-7.8 -12.8,-13.9 -21.6,-18.2C502.9,389.3 501.4,388.4 498.8,386.9zM519.9,389.7c18.8,16.3 28.9,37.9 40.1,58.6c5.4,10.1 11.2,20 16.4,30.3c5.9,11.8 15.6,18.4 28.1,21c6.7,1.3 13.5,2.2 20.3,2.4c23.1,0.9 45.8,-2.9 68.4,-7.3c13.7,-2.7 24.4,-10.1 32.5,-21.5c7.9,-11.2 12.4,-23.9 15.5,-37.1c5,-21.2 9.3,-42.6 14.7,-63.7c2.3,-8.9 2.2,-17.2 -0.2,-25.9c-0.8,-2.8 -1.7,-3.8 -4.6,-3.8c-17.1,0.3 -34.3,-0.4 -51.4,0.8c-39.1,2.7 -76.7,12.4 -113.6,25.4C564.4,376.5 542.5,382.6 519.9,389.7z"/>
+</vector>
diff --git a/res/drawable/icon_sunrise.xml b/res/drawable/icon_sunrise.xml
new file mode 100644
index 0000000..3698a3f
--- /dev/null
+++ b/res/drawable/icon_sunrise.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M278.6,215.2h-16.8c0-44.5-35.2-80.7-78.5-80.7c-43.3,0-78.5,36.2-78.5,80.7H88.1c0-54,42.7-98,95.3-98
+			C235.9,117.2,278.6,161.1,278.6,215.2"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M230,54.1L224.1,51.9L210.1,91.5L215.9,93.7z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M216.6,95.1l-7.8-2.9l14.8-41.7l7.8,2.9L216.6,95.1z M211.4,90.9l3.9,1.5l13.3-37.7l-3.9-1.5L211.4,90.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M304.6,116L301.5,110.4L265.9,131.5L269,137.1z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M268.6,138.6l-4.2-7.4l37.4-22.2l4.2,7.4L268.6,138.6z M267.3,131.9l2.1,3.7l33.7-20l-2.1-3.7L267.3,131.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M130.6,55.9L136.5,53.7L150.5,93.4L144.7,95.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M144,97l-14.8-41.7l7.8-2.9L151.9,94L144,97z M132,56.5l13.3,37.7l3.9-1.5l-13.3-37.7L132,56.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M56,117.8L59.1,112.3L94.7,133.4L91.6,138.9z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M92,140.4l-37.4-22.2l4.2-7.4L96.1,133L92,140.4z M57.4,117.4l33.7,20l2.1-3.7l-33.7-20L57.4,117.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M312.4,314H51.7c-2.3,0-4.2-1.9-4.2-4.3c0-2.4,1.9-4.3,4.2-4.3h260.6c2.3,0,4.2,1.9,4.2,4.3
+			C316.6,312,314.7,314,312.4,314z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M234,211.6h-2.1c0-27.4-21.6-49.6-48.3-49.6c-26.6,0-48.3,22.3-48.3,49.6h-2.1c0-28.6,22.6-51.8,50.4-51.8
+			C211.4,159.9,234,183.1,234,211.6z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M312.4,219.4H51.7c-2.6,0-4.8-2.2-4.8-4.9c0-2.7,2.1-4.9,4.8-4.9h260.6c2.6,0,4.8,2.2,4.8,4.9
+			C317.1,217.2,315,219.4,312.4,219.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M334.7,228.4H23.1c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6h311.6c0.9,0,1.6,0.7,1.6,1.6
+							C336.3,227.6,335.5,228.4,334.7,228.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M77.1,188l-42.9-4.5l0.9-8.5l42.9,4.5L77.1,188z M36.4,181.5l38.8,4.1l0.4-4.2l-38.8-4.1L36.4,181.5z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M111.3,112.4L82.6,79.2l6.2-5.7l28.7,33.2L111.3,112.4z M85.6,79.4l25.9,29.9l3.1-2.8L88.7,76.6L85.6,79.4z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M184.3,91.4l-8.3-0.1l0.3-44.4l8.3,0.1L184.3,91.4z M178.1,89.2l4.2,0l0.3-40.1l-4.2,0L178.1,89.2z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M284.8,173.9l-0.6-8.6l43-3.5l0.6,8.6L284.8,173.9z M286.4,167.3l0.3,4.3l38.8-3.1l-0.3-4.3L286.4,167.3z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M248.7,112l-6.1-5.9l29.5-32.4l6.1,5.9L248.7,112z M245.6,106.1l3,2.9l26.6-29.3l-3-2.9L245.6,106.1z"/>
+</vector>
diff --git a/res/drawable/icon_tea_time.xml b/res/drawable/icon_tea_time.xml
new file mode 100644
index 0000000..e1d9057
--- /dev/null
+++ b/res/drawable/icon_tea_time.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M92.4,213.4c-3.1-9.5-6.3-18.7-9.4-27.9c-0.1-0.4-0.8-0.9-1.3-0.9c-2.5-0.1-5.1-0.4-7.6-0.3
+			c-3.6,0.3-7.3,0.8-10.9,1.3c-1.4,0.1-1.6,1.1-1,2.3c0.6,1.3,1.4,2.5,2.1,3.5c5.4,6.6,11.8,11.9,18.9,16.5
+			C86.2,209.9,89.4,211.6,92.4,213.4z M189,39c0,0.3-0.1,0.5-0.1,0.8c-0.6,8.1-2.9,15.9-7.8,22.5c-3.1,4.3-6.9,8.1-10.4,12.1
+			c-2,2.4-4.3,4.6-6.1,7c-2.4,3.1-2.5,6.6-0.8,10.1c1,1.9,2.3,3.8,3.6,5.5c4.1,5.1,9.4,9,14.4,13.1c4,3.4,8,6.8,11.5,10.5
+			c4.1,4.3,6.5,9.5,6.1,15.8c0,0.1,0.1,0.1,0.3,0.3c3-3,5.5-6.1,5.1-10.8c-0.3-4.3-2.4-7.6-4.8-10.9c-2.1-2.8-4.4-5.5-6.5-8.1
+			c-3-3.9-5.9-7.9-7.8-12.5c-2.6-6.4-2.8-12.5,0.8-18.7c1.6-2.9,2.9-6,4-9.1C194.1,57.3,193.3,48,189,39z M77,159.9
+			c-2.5,0.1-4.8,0.3-7.1,0.5c-7,0.8-13.9,2.1-20.3,5.5c-9.5,5-14,13.8-12.3,24.3c1,6.1,3.9,11.4,7.5,16.4
+			c7.9,10.9,18.2,19.2,29.7,25.8c8.8,5,18,8.9,28.2,10.5c2.3,0.4,4.5,0.5,6.9,0.6c-3.4-5.6-6.6-10.9-9.9-16.3
+			c-0.3-0.4-0.9-0.8-1.4-0.9c-14.8-5.1-27.3-13.6-38.2-24.8c-3.1-3.3-6-6.6-7.4-11.1c-1.9-5.9,0.5-11.4,6-13.6
+			c1.1-0.5,2.3-1,3.5-1.1c5.3-0.5,10.4-0.9,15.5-1.3c0.8-0.1,1.5,0,2.4,0C79,169.4,78,164.7,77,159.9z M287.8,275.4
+			c-0.1,1-0.1,1.6-0.3,2.4c-0.8,4.1-3.5,6.9-6.6,9.3c-4.3,3.3-9.1,5.4-14,7.1c-16.9,6.1-34.5,8.5-52.4,9.6
+			c-13.1,0.9-26.4,0.9-39.6,0c-14.5-1-28.9-2.8-43.1-6.5c-7.8-2-15.3-4.6-22.2-8.9c-3-1.9-5.8-4.1-7.5-7.3c-0.8-1.4-1.1-3-1.8-4.5
+			c-5.3,4.9-5.9,10.9-1.1,16.1c2.4,2.6,5.3,4.9,8.1,6.9c6.6,4.4,14,7.1,21.5,9.4c17.8,5.5,36.1,7.8,54.6,8.5
+			c19.7,0.8,39.3-0.4,58.7-4c11.4-2.3,22.5-5.1,33-10.3c5.4-2.5,10.4-5.5,14.4-10c1.9-2.3,3.5-4.6,3.6-7.8
+			C293.3,281.3,290.8,278.4,287.8,275.4z M196.4,302c12.6,0,25.3-0.9,37.9-2.6c10.9-1.6,21.7-3.8,32-7.6c5.4-2,10.8-4.3,14.9-8.4
+			c1.5-1.5,2.8-3.5,3.6-5.5c1-2.6,0-4.9-2.4-6.4c-5.8-3.8-12-6.4-18.5-8.6c-1.4-0.5-2.3-0.3-3.4,0.6c-9.9,8.4-21.2,14.5-33.5,18.4
+			c-13.5,4.1-27.4,5-41.4,4.3c-13.6-0.9-26.7-4.3-38.9-10.4c-6.6-3.4-12.8-7.5-18.5-12.3c-0.5-0.4-1.4-0.9-1.9-0.8
+			c-7.8,2.5-15.3,5.6-21.8,10.5c-0.6,0.5-1.1,1.5-1.3,2.3c-0.4,2.3,0.5,4.3,2,6.1c2.8,3.5,6.5,5.8,10.4,7.6
+			c9.8,4.8,20.3,7.3,30.8,9.1C163,301,179.6,302.1,196.4,302z M193.8,134c-0.6-1.8-1.1-3.3-1.8-4.6c-0.3-0.5-1.1-1-1.8-1
+			c-3.9,0-7.8,0.1-11.6,0.3c-14.5,0.5-28.9,1.6-43.2,3.8c-11.3,1.8-22.4,3.9-33.2,7.6c-4.6,1.6-9.3,3.6-13.3,6.5
+			c-2.8,2-3.6,4.6-3,7.9c2.8,13.8,5.9,27.4,10.5,40.8c5.8,16.4,13.1,32,24,45.7c11.8,14.9,26.3,25.7,44.4,31.3
+			c12.6,3.9,25.7,4.6,38.7,3.8c13.5-1,26.4-4.6,38.2-11.5c14.4-8.4,25.4-20.3,34.2-34.3c14.8-23.5,21.9-49.8,27-76.9
+			c0.5-2.5-0.3-4.6-2.4-6.1c-1.6-1.1-3.3-2.3-4.9-3.3c-5.4-2.9-11.1-4.9-17-6.4c-20.7-5.5-41.8-7.6-63.2-8.8c-1.5-0.1-3,0-4.4,0
+			c-0.5,1.8-1,3.4-1.5,5.3c0.6,0.1,1.3,0.1,1.9,0.3c14.6,0.5,29.2,1.9,43.7,4.6c8.6,1.6,17.1,3.6,25.2,7.4c2.8,1.4,5.5,2.9,7.5,5.3
+			c2.1,2.6,2.1,5.5-0.1,8c-1.1,1.3-2.4,2.5-3.8,3.1c-3.9,1.9-7.9,3.9-12,5.3c-15.5,5-31.5,6.8-47.7,8c-15.3,1.1-30.7,1.4-45.9,0.8
+			c-16-0.6-32-2-47.8-5.3c-8-1.6-15.9-3.5-23.2-7.4c-2.3-1.1-4.5-2.8-6.3-4.6c-2.5-2.6-2.4-5.8,0.3-8.3c1.8-1.6,3.8-3,5.8-4.3
+			c5.1-2.8,10.8-4.4,16.4-5.9c20.2-4.9,40.7-6.5,61.2-7C187.8,133.9,190.6,134,193.8,134z M118.9,254c-0.9-0.4-1.8-1-2.5-1
+			c-8.6,1-17-0.1-25.2-2.6c-22.5-7.3-41.3-19.9-55.2-39.3c-4.5-6.3-7.6-13.3-8.5-21.2c-1.4-13,3.4-23.3,14.1-30.7
+			c6.3-4.4,13.4-6.5,20.8-7.8c4.1-0.6,8.4-0.9,12.5-1.4c0.5-0.1,1.3-0.5,1.3-1c0.9-5,4-8.5,7.9-11.3c6.4-4.5,13.6-7.1,21.2-9.3
+			c13-3.8,26.4-6.3,39.9-7.5c11.9-1.1,23.8-1.8,35.7-2.6c0.4,0,0.8-0.1,1.5-0.1c-0.9-0.8-1.6-1.3-2.3-1.9c-5-4.3-10-8.4-14.8-12.8
+			c-3.4-3.1-5.9-6.8-7.5-11c-1.9-5-1.4-9.8,1.6-14.1c1.8-2.5,3.9-4.9,5.9-7.1c3.4-3.9,7.1-7.5,10.3-11.6c6-8,7.9-17.3,7.5-27
+			c-0.3-4.1-1.1-8.3-1.4-12.5c-0.1-1.8,0.3-3.6,0.4-5.5c2.1,0.3,4,0.4,5.8,0.6c0.4,2.3,0.5,4.5,1.3,6.5c1.5,4.1,3.1,8,4.9,12
+			c3,6.9,5.3,13.9,5.3,21.4c0,8.6-2.6,16.5-6.8,23.9c-2.3,4-2.4,8-0.8,12.1c1.9,4.9,4.9,8.9,8,12.9c3.5,4.4,7.3,8.5,9.6,13.8
+			c0.1,0.4,0.9,0.6,1.3,0.6c5.5,0.4,10.9,0.5,16.4,1c20.3,1.5,40.3,4,59.8,10c5.6,1.8,11.1,3.9,16.3,7c1.8,1.1,3.5,2.5,5.1,3.9
+			c4.5,4,5.8,9.1,4.8,14.8c-2.9,15.4-6.5,30.5-11.8,45.3c-6.3,17.4-14.4,33.7-26,48.1c-1.5,1.9-3.3,3.8-4.9,5.8
+			c4,1.8,7.8,3.4,11.5,5.3c5.4,2.6,10.3,6,14.4,10.3c8.9,9.1,9.1,21,0.6,30.4c-5.1,5.8-11.6,9.5-18.5,12.6
+			c-11.9,5.5-24.4,8.8-37.3,11c-18.2,3.3-36.4,4.4-54.8,3.8c-22-0.6-43.7-3.4-64.7-10.5c-9.3-3.1-18.2-7.1-25.7-13.6
+			c-3.8-3.3-7-7-8.5-11.9c-2.6-8-0.3-15,5.1-21.2c5.1-5.8,11.6-9.6,18.7-12.8c2.5-1.1,5.1-2.3,7.8-3.4
+			C118.8,254.3,118.8,254.2,118.9,254z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M92.4,213.4c-3.1-9.5-6.3-18.7-9.4-27.9c-0.1-0.4-0.8-0.9-1.3-0.9c-2.5-0.1-5.1-0.4-7.6-0.3
+				c-3.6,0.3-7.3,0.8-10.9,1.3c-1.4,0.1-1.6,1.1-1,2.3c0.6,1.3,1.4,2.5,2.1,3.5c5.4,6.6,11.8,11.9,18.9,16.5
+				C86.2,209.9,89.4,211.6,92.4,213.4z M189,39c0,0.3-0.1,0.5-0.1,0.8c-0.6,8.1-2.9,15.9-7.8,22.5c-3.1,4.3-6.9,8.1-10.4,12.1
+				c-2,2.4-4.3,4.6-6.1,7c-2.4,3.1-2.5,6.6-0.8,10.1c1,1.9,2.3,3.8,3.6,5.5c4.1,5.1,9.4,9,14.4,13.1c4,3.4,8,6.8,11.5,10.5
+				c4.1,4.3,6.5,9.5,6.1,15.8c0,0.1,0.1,0.1,0.3,0.3c3-3,5.5-6.1,5.1-10.8c-0.3-4.3-2.4-7.6-4.8-10.9c-2.1-2.8-4.4-5.5-6.5-8.1
+				c-3-3.9-5.9-7.9-7.8-12.5c-2.6-6.4-2.8-12.5,0.8-18.7c1.6-2.9,2.9-6,4-9.1C194.1,57.3,193.3,48,189,39z M77,159.9
+				c-2.5,0.1-4.8,0.3-7.1,0.5c-7,0.8-13.9,2.1-20.3,5.5c-9.5,5-14,13.8-12.3,24.3c1,6.1,3.9,11.4,7.5,16.4
+				c7.9,10.9,18.2,19.2,29.7,25.8c8.8,5,18,8.9,28.2,10.5c2.3,0.4,4.5,0.5,6.9,0.6c-3.4-5.6-6.6-10.9-9.9-16.3
+				c-0.3-0.4-0.9-0.8-1.4-0.9c-14.8-5.1-27.3-13.6-38.2-24.8c-3.1-3.3-6-6.6-7.4-11.1c-1.9-5.9,0.5-11.4,6-13.6
+				c1.1-0.5,2.3-1,3.5-1.1c5.3-0.5,10.4-0.9,15.5-1.3c0.8-0.1,1.5,0,2.4,0C79,169.4,78,164.7,77,159.9z M287.8,275.4
+				c-0.1,1-0.1,1.6-0.3,2.4c-0.8,4.1-3.5,6.9-6.6,9.3c-4.3,3.3-9.1,5.4-14,7.1c-16.9,6.1-34.5,8.5-52.4,9.6
+				c-13.1,0.9-26.4,0.9-39.6,0c-14.5-1-28.9-2.8-43.1-6.5c-7.8-2-15.3-4.6-22.2-8.9c-3-1.9-5.8-4.1-7.5-7.3c-0.8-1.4-1.1-3-1.8-4.5
+				c-5.3,4.9-5.9,10.9-1.1,16.1c2.4,2.6,5.3,4.9,8.1,6.9c6.6,4.4,14,7.1,21.5,9.4c17.8,5.5,36.1,7.8,54.6,8.5
+				c19.7,0.8,39.3-0.4,58.7-4c11.4-2.3,22.5-5.1,33-10.3c5.4-2.5,10.4-5.5,14.4-10c1.9-2.3,3.5-4.6,3.6-7.8
+				C293.3,281.3,290.8,278.4,287.8,275.4z M196.4,302c12.6,0,25.3-0.9,37.9-2.6c10.9-1.6,21.7-3.8,32-7.6c5.4-2,10.8-4.3,14.9-8.4
+				c1.5-1.5,2.8-3.5,3.6-5.5c1-2.6,0-4.9-2.4-6.4c-5.8-3.8-12-6.4-18.5-8.6c-1.4-0.5-2.3-0.3-3.4,0.6c-9.9,8.4-21.2,14.5-33.5,18.4
+				c-13.5,4.1-27.4,5-41.4,4.3c-13.6-0.9-26.7-4.3-38.9-10.4c-6.6-3.4-12.8-7.5-18.5-12.3c-0.5-0.4-1.4-0.9-1.9-0.8
+				c-7.8,2.5-15.3,5.6-21.8,10.5c-0.6,0.5-1.1,1.5-1.3,2.3c-0.4,2.3,0.5,4.3,2,6.1c2.8,3.5,6.5,5.8,10.4,7.6
+				c9.8,4.8,20.3,7.3,30.8,9.1C163,301,179.6,302.1,196.4,302z M193.8,134c-0.6-1.8-1.1-3.3-1.8-4.6c-0.3-0.5-1.1-1-1.8-1
+				c-3.9,0-7.8,0.1-11.6,0.3c-14.5,0.5-28.9,1.6-43.2,3.8c-11.3,1.8-22.4,3.9-33.2,7.6c-4.6,1.6-9.3,3.6-13.3,6.5
+				c-2.8,2-3.6,4.6-3,7.9c2.8,13.8,5.9,27.4,10.5,40.8c5.8,16.4,13.1,32,24,45.7c11.8,14.9,26.3,25.7,44.4,31.3
+				c12.6,3.9,25.7,4.6,38.7,3.8c13.5-1,26.4-4.6,38.2-11.5c14.4-8.4,25.4-20.3,34.2-34.3c14.8-23.5,21.9-49.8,27-76.9
+				c0.5-2.5-0.3-4.6-2.4-6.1c-1.6-1.1-3.3-2.3-4.9-3.3c-5.4-2.9-11.1-4.9-17-6.4c-20.7-5.5-41.8-7.6-63.2-8.8c-1.5-0.1-3,0-4.4,0
+				c-0.5,1.8-1,3.4-1.5,5.3c0.6,0.1,1.3,0.1,1.9,0.3c14.6,0.5,29.2,1.9,43.7,4.6c8.6,1.6,17.1,3.6,25.2,7.4c2.8,1.4,5.5,2.9,7.5,5.3
+				c2.1,2.6,2.1,5.5-0.1,8c-1.1,1.3-2.4,2.5-3.8,3.1c-3.9,1.9-7.9,3.9-12,5.3c-15.5,5-31.5,6.8-47.7,8c-15.3,1.1-30.7,1.4-45.9,0.8
+				c-16-0.6-32-2-47.8-5.3c-8-1.6-15.9-3.5-23.2-7.4c-2.3-1.1-4.5-2.8-6.3-4.6c-2.5-2.6-2.4-5.8,0.3-8.3c1.8-1.6,3.8-3,5.8-4.3
+				c5.1-2.8,10.8-4.4,16.4-5.9c20.2-4.9,40.7-6.5,61.2-7C187.8,133.9,190.6,134,193.8,134z M118.9,254c-0.9-0.4-1.8-1-2.5-1
+				c-8.6,1-17-0.1-25.2-2.6c-22.5-7.3-41.3-19.9-55.2-39.3c-4.5-6.3-7.6-13.3-8.5-21.2c-1.4-13,3.4-23.3,14.1-30.7
+				c6.3-4.4,13.4-6.5,20.8-7.8c4.1-0.6,8.4-0.9,12.5-1.4c0.5-0.1,1.3-0.5,1.3-1c0.9-5,4-8.5,7.9-11.3c6.4-4.5,13.6-7.1,21.2-9.3
+				c13-3.8,26.4-6.3,39.9-7.5c11.9-1.1,23.8-1.8,35.7-2.6c0.4,0,0.8-0.1,1.5-0.1c-0.9-0.8-1.6-1.3-2.3-1.9c-5-4.3-10-8.4-14.8-12.8
+				c-3.4-3.1-5.9-6.8-7.5-11c-1.9-5-1.4-9.8,1.6-14.1c1.8-2.5,3.9-4.9,5.9-7.1c3.4-3.9,7.1-7.5,10.3-11.6c6-8,7.9-17.3,7.5-27
+				c-0.3-4.1-1.1-8.3-1.4-12.5c-0.1-1.8,0.3-3.6,0.4-5.5c2.1,0.3,4,0.4,5.8,0.6c0.4,2.3,0.5,4.5,1.3,6.5c1.5,4.1,3.1,8,4.9,12
+				c3,6.9,5.3,13.9,5.3,21.4c0,8.6-2.6,16.5-6.8,23.9c-2.3,4-2.4,8-0.8,12.1c1.9,4.9,4.9,8.9,8,12.9c3.5,4.4,7.3,8.5,9.6,13.8
+				c0.1,0.4,0.9,0.6,1.3,0.6c5.5,0.4,10.9,0.5,16.4,1c20.3,1.5,40.3,4,59.8,10c5.6,1.8,11.1,3.9,16.3,7c1.8,1.1,3.5,2.5,5.1,3.9
+				c4.5,4,5.8,9.1,4.8,14.8c-2.9,15.4-6.5,30.5-11.8,45.3c-6.3,17.4-14.4,33.7-26,48.1c-1.5,1.9-3.3,3.8-4.9,5.8
+				c4,1.8,7.8,3.4,11.5,5.3c5.4,2.6,10.3,6,14.4,10.3c8.9,9.1,9.1,21,0.6,30.4c-5.1,5.8-11.6,9.5-18.5,12.6
+				c-11.9,5.5-24.4,8.8-37.3,11c-18.2,3.3-36.4,4.4-54.8,3.8c-22-0.6-43.7-3.4-64.7-10.5c-9.3-3.1-18.2-7.1-25.7-13.6
+				c-3.8-3.3-7-7-8.5-11.9c-2.6-8-0.3-15,5.1-21.2c5.1-5.8,11.6-9.6,18.7-12.8c2.5-1.1,5.1-2.3,7.8-3.4
+				C118.8,254.3,118.8,254.2,118.9,254z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+					c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+					c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+					C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+					c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+					c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+					c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3C209,2.7,209,1.8,209,0.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+						c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+						c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+						C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+						c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+						c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+						c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3
+						C209,2.7,209,1.8,209,0.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M208.3,14.8c-0.4,0.4-0.5,0.5-0.5,0.6c-4.8,11-4.8,21.9,0.6,32.7c1.8,3.4,2,7,1.1,10.6
+						c-1.3,5.1-4.1,9.4-7,13.6c-1.5,2.3-3.1,4.6-4.4,7.1c-1.4,2.5-2,5.1-1.6,8c0.5,3.9,3,6.6,5.9,9.6c-2.5-8.3,1.5-13.9,6.5-19
+						c1.9-2,4-3.8,6-5.8c3.4-3.3,6.8-6.5,9-10.8c2.4-4.4,2.1-8.4-0.8-12.4c-1.1-1.4-2.1-2.8-3.3-4.1c-3.9-4.5-7.4-9.4-9.3-15.1
+						C208.8,25.3,208.2,20.3,208.3,14.8z M209,0.8h2.1c0.9,2.6,0.1,5.3-0.1,7.9c-1.1,10-0.4,19.5,5.4,28.2c2,3.1,4.5,5.9,6.8,8.8
+						c1.9,2.4,3.8,4.9,4.4,7.9c0.8,3.5-0.1,6.6-1.8,9.6c-2.8,5-7,8.9-11,12.9c-2.9,2.8-5.8,5.6-8.1,8.8c-3.6,4.8-3.8,9.9-0.4,14.9
+						c1.4,2,2.6,4.1,4,6.3c-0.6,0.5-1.3,0.9-2,1.4c-4-4.4-8.1-8.5-11.9-13.1c-3.1-4-3.6-8.8-1.6-13.4c1.5-3.4,3.6-6.5,5.4-9.8
+						c1.9-3.4,4.1-6.8,5.8-10.4c1.9-3.9,1.8-7.9-0.3-11.9c-5.3-10.9-5.3-21.9-0.9-33c1.5-4,2.6-8.1,3.9-12.3
+						C209,2.7,209,1.8,209,0.8z"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M279.8,179.6c-0.9,0.4-1.4,0.5-1.9,0.8c-5.5,1.6-11.1,3.4-16.6,4.9
+							c-1.4,0.4-1.8,0.9-1.9,2.3c-0.9,12.4-3.1,24.4-7,36.1c-3.6,11.3-8.9,21.7-14.4,32c-0.3,0.5-0.5,1-0.9,1.8c0.9-0.5,1.5-0.8,2-1
+							c0.4-0.3,0.6-0.5,1-0.8c10.9-9.4,19-20.8,25.2-33.7C271.5,208.3,276,194.3,279.8,179.6z M231.9,262c1.3-2.5,2.3-5.1,3.6-7.6
+							c5.5-10.4,10.8-20.8,14.4-32c3.9-12.1,6.1-24.7,7-37.4c0.1-1.1,0.4-1.5,1.5-1.8c7.4-2.1,14.6-4.4,21.9-6.6
+							c0.6-0.1,1.5-0.3,1.8,0c0.4,0.4,0.5,1.3,0.3,1.8c-3.8,15.4-8.5,30.4-15.3,44.8c-6.4,13.1-14.5,25-25.9,34.3
+							c-2.6,2.1-6,3.3-9,4.9C232.2,262.3,232.1,262.2,231.9,262z"/>
+</vector>
diff --git a/res/drawable/icon_timestamp.xml b/res/drawable/icon_timestamp.xml
new file mode 100644
index 0000000..72656c6
--- /dev/null
+++ b/res/drawable/icon_timestamp.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="360.0"
+    android:viewportWidth="360.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#00000000"
+        android:pathData="M180,183m-143.9,0a143.9,143.9 0,1 1,287.8 0a143.9,143.9 0,1 1,-287.8 0"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="19.0452"/>
+    <path android:fillColor="?attr/fillColorSelector" android:pathData="M180,65.2c65,0,117.8,52.9,117.8,117.8S245,300.8,180,300.8S62.2,248,62.2,183S115,65.2,180,65.2 M180,62.4
+			c-66.5,0-120.6,54.1-120.6,120.6S113.5,303.6,180,303.6S300.6,249.5,300.6,183S246.5,62.4,180,62.4"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M71.1,137.7L288.4,137.7"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="4.4394"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M72.1,232.2L289.4,232.2"
+        android:strokeColor="?attr/fillColorSelector" android:strokeWidth="4.4394"/>
+</vector>
diff --git a/res/drawable/icon_tools.xml b/res/drawable/icon_tools.xml
new file mode 100644
index 0000000..0a6c98a
--- /dev/null
+++ b/res/drawable/icon_tools.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:height="24dp" android:viewportHeight="66.0"
+    android:viewportWidth="69.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#00000000"
+        android:pathData="M55.01,4.19C55.07,4.21 54.95,4.15 55.01,4.19L55.01,4.19Z"
+        android:strokeColor="#020302" android:strokeWidth="4.8"/>
+    <path android:fillColor="#00000000"
+        android:pathData="M66.1,22.2C65.62,21.39 64.51,21.16 63.69,21.64L54.02,27.3C53.02,27.89 51.55,27.67 50.77,26.81C50.77,26.81 48.49,24.34 46.84,21.57C45.26,18.92 44.19,15.99 44.19,15.99C43.8,14.91 44.3,13.53 45.3,12.95L55.05,7.26C55.88,6.78 56.23,5.68 55.74,4.87C55.58,4.6 55.26,4.33 55.01,4.19C50.08,2.32 44.38,2.59 39.49,5.45C32.62,9.47 29.46,17.32 31.12,24.63L31.06,24.68C31.6,26.88 30.96,29.32 29.21,30.99L5.16,49.01C2.36,51.68 2.27,57.29 4.97,60.07C7.66,62.85 12.12,64.13 14.93,61.46L39.72,40.34C40.86,39.26 42.61,38.37 44.37,37.99C48.75,39.04 53.54,38.48 57.73,36.03C62.52,33.23 65.5,28.51 66.31,23.46C66.39,23.06 66.33,22.58 66.1,22.2L66.1,22.2Z"
+        android:strokeColor="#020302" android:strokeWidth="4.8"/>
+    <path android:fillColor="#020302"
+        android:pathData="M14.19,54.12C14.19,55.51 13.05,56.63 11.65,56.63C10.25,56.63 9.12,55.51 9.12,54.12C9.12,52.74 10.25,51.61 11.65,51.61C13.05,51.61 14.19,52.74 14.19,54.12"
+        android:strokeColor="#00000000" android:strokeWidth="1"/>
+</vector>
diff --git a/res/drawable/icon_yum.xml b/res/drawable/icon_yum.xml
new file mode 100644
index 0000000..9a7dfa6
--- /dev/null
+++ b/res/drawable/icon_yum.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector android:height="24dp" android:viewportHeight="831.0"
+    android:viewportWidth="1053.0" android:width="30dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#ffffff" android:pathData="M354.1,730.5c-4.2,14.1 -8.8,27.5 -12,41.2c-2.2,9.7 -6.6,14.8 -16.7,16.8c-13.7,2.7 -26.8,8.8 -40.5,10.5c-38.8,4.8 -75.8,-1.7 -108.6,-24.2c-20.2,-13.8 -32.7,-33.3 -35.4,-57.8c-2.6,-23.5 -4.7,-47.1 -5.6,-70.7c-0.8,-18.9 1.6,-37.8 11,-54.7c4.7,-8.5 11.4,-15.9 17,-23.8c1.4,-2 3,-4.1 3.4,-6.3c4.4,-22.9 8.7,-45.8 12.8,-68.7c0.3,-1.6 -0.2,-3.7 -1.1,-5c-23.2,-31.9 -46.6,-63.8 -69.9,-95.6c-0.9,-1.3 -2.3,-2.5 -3.8,-3c-20,-6.8 -34.7,-20 -46.1,-37.3c-13,-19.7 -23,-40.9 -30.4,-63.3c-11.7,-35.4 -3.5,-67 19,-95.6c20.6,-26.3 47.7,-39.5 81.2,-37.9c27.6,1.3 50,14 68.7,33.6c8.9,9.4 17.3,19.4 25.8,29.2c1.1,1.2 2.1,2.5 4.2,5c4.6,-9.6 9.6,-18.1 12.8,-27.2c8.3,-23.9 16.8,-47.7 30.7,-69.1c22.4,-34.4 54.4,-49.2 94.8,-46.7c7,0.4 13.1,-0.5 19.5,-3.6C441.9,48.7 502,36.2 565,39.3c80.3,4 152,31.2 214.9,81.3c4.3,3.4 7.6,4.4 13.2,2.6c49.4,-16.7 108.7,1.3 138.3,41.6c12.6,17.2 19.3,36.6 18.8,57.9c-0.7,30.6 -2.3,61.2 -3.8,91.8c-0.6,12.8 -1.9,25.6 -3.2,38.3c-0.4,3.7 1.6,4 4.2,4.6c26.3,6.9 46.3,22.2 59.7,45.8c10.6,18.7 14.1,39.1 12.5,60.2c-2.7,36.8 -15.8,69.7 -40,97.6c-29.2,33.7 -66.3,50.4 -111.1,48.9c-4,-0.1 -6.2,1.1 -8.4,4.4c-57.1,85.8 -135.8,141 -236.8,162.1c-93.2,19.5 -181.7,4.6 -264.4,-43.2C357.6,732.4 356.1,731.6 354.1,730.5zM343.3,704c1.8,1.2 3.2,2.1 4.5,3c82.1,54.4 171.9,73.5 268.3,54.4c101.6,-20.1 179.7,-75.9 235.1,-163.3c2.6,-4.1 4.9,-5.8 10.1,-5.1c24.2,3.3 47.1,-1.4 68.6,-12.7c48.4,-25.4 80,-85.3 72.8,-139.6c-4.4,-32.8 -22.9,-55.5 -54.5,-66.4c-7,-2.4 -14.5,-3.1 -22.3,-4.7c1.5,-18.8 3,-37.8 4.6,-56.9c2.5,-31 5.2,-62 3.7,-93.3c-0.9,-17.7 -6.6,-33.6 -17.5,-47.5c-28.4,-36.4 -87,-49.8 -128.8,-29.5c-2.5,1.2 -4.3,2.1 -7.1,-0.2c-62.4,-53.6 -134.7,-82.9 -216.9,-87c-58.8,-2.9 -115,8.3 -168.1,33.7c-10.5,5 -20.5,8 -32.6,7c-36.3,-2.8 -64.2,12.5 -82,44.2c-7.8,13.9 -14.6,28.5 -19.8,43.5c-6.1,17.7 -12.5,35 -23.3,50.4c-2.7,3.9 -4.7,8.4 -7,12.6c-0.6,1.1 -1.3,2.1 -2.2,3.6c-1.5,-1.8 -2.6,-3.2 -3.8,-4.5c-14.3,-16.5 -28,-33.6 -43.1,-49.2c-25.2,-25.9 -60,-32.7 -90.7,-18.7c-21.8,9.9 -35.5,27.4 -45.4,48.5c-6.6,14.2 -8.6,29 -5.2,44.3c6.5,29 19.2,55.2 36.7,79.1c9.1,12.5 21.4,20.8 36.3,25.2c2,0.6 4,2.3 5.3,4.1c25.4,34.5 50.7,69 75.9,103.6c1.4,1.9 2,5 1.6,7.2c-4.7,26.2 -9.5,52.4 -14.6,78.5c-0.6,3.1 -2.6,6.4 -4.9,8.6c-9,8.6 -15.7,18.5 -19.9,30.1c-5.2,14.5 -6.4,29.7 -5.6,44.8c1,18.6 3.2,37.1 4.5,55.7c1.7,24.6 13,43.4 33.7,56.4c25.4,16.1 53.7,20.8 83.2,20c17.6,-0.5 33.6,-7.8 50.2,-12.4c1.3,-0.4 2.6,-2.4 3.1,-3.9c3.1,-10 6.3,-20 9,-30.1C338,726.9 340.5,715.7 343.3,704z"/>
+    <path android:fillColor="#ffffff" android:pathData="M776.1,200.2c0.6,-1.6 1.3,-2.9 1.7,-4.3c5.5,-18.6 18.5,-28.9 37,-32.2c24.5,-4.4 47.5,0 67.8,14.7c16.8,12.1 23.8,29.4 22.9,49.5c-1.3,32.6 -3.3,65.2 -5.2,97.7c-1.3,23.3 -2.9,46.5 -4.3,69.8c-0.1,1.6 0,3.3 0,5.6c8.2,-0.5 15.9,-0.8 23.7,-1.4c26.4,-2.2 49.1,14.9 54,40.9c8,42.9 -20.6,107.6 -76.2,121.8c-24.5,6.2 -47.6,3.3 -68.4,-11.8c-0.5,-0.4 -1.1,-0.8 -1.7,-1.1c-0.2,-0.1 -0.6,-0.1 -1.7,-0.1c0.2,2.8 0.6,5.6 0.4,8.3c-0.2,2.6 -0.4,5.6 -1.6,7.8c-5.5,9.8 -12.9,18 -21.9,25c-4.8,3.8 -7.9,9.8 -11.9,14.7c-52.5,64.7 -119.9,104.2 -202.6,114.5c-99.1,12.3 -185.5,-16.9 -258,-85.9c-0.8,-0.8 -1.7,-1.6 -2.5,-2.4c-0.2,-0.2 -0.6,-0.2 -1.3,-0.3c-2.4,14.4 -4.4,28.9 -7.3,43.1c-4.9,23.6 -10.4,47.1 -15.8,70.5c-0.4,1.8 -2.4,4 -4.1,4.7c-28.8,11.4 -57,6.9 -84.6,-4c-17.5,-6.9 -28.5,-19.5 -29.7,-39.4c-1.2,-20.4 -3.5,-40.8 -4.3,-61.3c-0.3,-8.7 1.2,-17.6 3.4,-26.1c2.8,-11 9.9,-19.4 19.8,-25.4c1.7,-1 3.3,-3.3 3.7,-5.2c6.7,-34.8 13.3,-69.6 19.6,-104.5c0.4,-2.3 -0.3,-5.4 -1.7,-7.3c-30,-41.2 -60.2,-82.3 -90.3,-123.4c-1.9,-2.6 -4,-3.9 -7.3,-4.2c-10.6,-1 -19.5,-5.7 -26,-14.2c-15.5,-20.2 -26.1,-42.9 -32.4,-67.5c-4.4,-17.3 2.7,-31.7 12.7,-45c19.9,-26.3 52.7,-30.1 76.7,-7.3c15.4,14.6 28.9,31.3 42.5,47.7c15.5,18.7 30.3,38.1 45.3,57.2c0.8,1 1.7,2 2.7,3.2c4,-10.5 8.3,-20.5 11.5,-30.8c4.3,-13.8 7.8,-27.8 11.4,-41.8c7.5,-28.8 14.5,-57.8 27.9,-84.7c3.3,-6.5 7.2,-12.8 11.5,-18.6c12.4,-16.9 29.7,-23.2 50.2,-22.2c13.8,0.7 27,3.4 39.1,10.6c1.4,0.9 4.4,0.1 6.3,-0.8c27.8,-14 57.1,-24.1 87.9,-28.9c93.3,-14.5 177.1,7.4 250.6,66.9C756.1,181 765.7,190.7 776.1,200.2zM818.8,325.4c0.1,0.9 0.2,1.7 0.1,2.5c-0.8,17.6 -1.8,35.3 -2.4,52.9c-0.8,25 -2,50 2.4,74.8c3.2,17.9 7.6,35.5 17.3,51.2c13.6,22 35.4,29.2 59.1,19.1c20.4,-8.6 32.2,-25.1 39.5,-45.3c3.9,-10.7 6.3,-21.8 4.1,-33.3c-1.5,-7.9 -7,-12.4 -14.4,-12.2c-2.2,8.2 -3.7,16.6 -6.9,24.4c-3.1,7.5 -7.1,15.2 -12.5,21.3c-8.8,9.8 -23.5,8.1 -31.1,-2.7c-2.6,-3.8 -4.6,-8.1 -6.1,-12.5c-5.1,-14.8 -6.2,-30.3 -6.8,-45.8c-1.5,-36.9 2.6,-73.5 5.1,-110.2c1.9,-28.2 2.6,-56.5 3.9,-84.8c0.4,-9.6 -4.3,-16.2 -12.3,-20.6c-11,-6 -22.8,-8 -35.2,-6.3c-5.8,0.8 -9.5,3.3 -11.6,9.2c-14.4,42 -23.3,85.3 -31.2,128.9c-4.9,27.5 -9.9,55 -14.9,82.5c-0.2,1.4 -1,2.7 -1.5,4c-0.5,-0.1 -0.9,-0.1 -1.4,-0.2c-0.3,-1.9 -0.8,-3.8 -0.9,-5.6c-1,-15.4 -2.4,-30.9 -2.9,-46.3c-1.3,-34.6 -2.3,-69.2 -3.2,-103.8c-0.3,-9.5 -4.8,-15.7 -13.1,-19.5c-9.5,-4.5 -19.6,-4.8 -29.8,-3.7c-7.2,0.7 -11.7,4.1 -12.6,11.7c-0.3,2.3 -1.2,4.5 -1.7,6.8c-11.6,54.8 -23.3,109.7 -34.9,164.5c-0.3,1.6 -1,3.2 -1.5,4.8c-0.5,0 -1,-0.1 -1.5,-0.1c-0.3,-2 -1,-4 -1,-5.9c0,-22.5 -0.8,-45 0.3,-67.4c1.6,-33.9 4.4,-67.8 6.9,-101.7c0.4,-6 -1.8,-9.9 -6.6,-12.8c-8.8,-5.4 -18.5,-7.2 -28.7,-6.9c-3.7,0.1 -6.1,1.9 -7,5.3c-1.8,6.7 -3.8,13.5 -4.9,20.3c-5.4,33.6 -6.5,67.6 -6.5,101.6c0,26.8 0.8,53.6 2.8,80.3c1.7,22.9 5.1,45.6 8.9,68.3c2.4,14.3 7.9,27.9 17.9,39c12.4,13.8 32.2,14.7 44.2,2c1.5,-1.6 2.7,-4.4 2.4,-6.5c-3.2,-25.8 -1.7,-51.6 0.6,-77.3c3.7,-40.1 10.7,-79.8 18.6,-119.3c0.7,-3.4 2.1,-5 6,-4.4c0.2,1.5 0.6,3.1 0.7,4.7c1.1,15.6 1.5,31.3 3.2,46.8c4.4,39.4 9,78.7 14.2,118c1.7,13.3 4.9,26.6 12.4,38.2c10.1,15.6 31.5,17 43.6,2.9c1.1,-1.3 1.8,-3.6 1.7,-5.3c-0.5,-12.5 -2.4,-25 -1.9,-37.4c1.2,-29.6 2.7,-59.2 5.5,-88.7c3,-31.5 8.7,-62.6 16.8,-93.2C811.4,327 813.1,324.1 818.8,325.4zM273.6,413c-0.7,-0.9 -1.7,-2.1 -2.7,-3.4C236.2,365 201.8,320.3 166.8,276c-10,-12.6 -21.2,-24.4 -32.4,-35.9c-6,-6.2 -12.4,-6.5 -18.2,-3c-6.9,4.2 -14,16.4 -12.5,22.4c4.3,17.3 12.2,33 21.7,48c4.6,7.2 5.4,7.3 13.2,3.2c3.2,-1.7 6.1,-2.8 8.7,0.9c1,1.5 2.3,2.8 3.4,4.3c35.8,48.5 71.5,97.1 107.6,145.4c5,6.7 6.5,12.6 4.8,20.9c-8.8,44.6 -17.1,89.2 -25.4,133.9c-0.8,4.5 -2.4,6.4 -7.4,6.2c-10.1,-0.4 -13.4,3.1 -14.4,13c-2.2,21.9 1.9,43.5 3.4,65.2c0.5,7.3 4.2,10.7 10.2,13.1c12.1,4.7 24.7,6.5 37.6,7.2c4.8,0.3 8,-1 8.3,-6.5c0.2,-2.8 1.3,-5.5 1.8,-8.3c6.4,-37.2 12.9,-74.4 19.1,-111.7c8.7,-52.5 17,-105.1 25.9,-157.6c10.3,-60.9 21.3,-121.6 36.1,-181.6c6.9,-27.9 13.9,-55.9 27,-81.8c0.7,-1.4 -0.1,-4.2 -1.1,-5.7c-5.5,-8.2 -35,-10.8 -40.6,-3.7c-0.5,0.7 -1.3,1.1 -1.8,1.7c-4,6.1 -8.5,12 -11.6,18.5c-10.8,22.8 -17.6,47.1 -23,71.6C295.5,307.9 284.7,360.4 273.6,413zM500.2,485.7c0.7,0.2 1.4,0.4 2.2,0.7c0.5,3.1 1,6.2 1.6,9.2c3.3,16.8 8.2,33 19.2,46.6c18.9,23.2 52.1,22.6 70.3,-1c0.7,-0.9 1.5,-2.5 1.3,-3.5c-2.5,-9.2 -5.2,-18.4 -7.8,-27.7c-15.9,13.4 -28.1,11.3 -37.8,-7.3c-4.1,-7.9 -7.8,-16.6 -8.8,-25.2c-2.6,-22.6 -4.2,-45.4 -4.9,-68.2c-0.9,-31 -0.5,-62 -0.8,-93c-0.1,-11.8 -1,-23.6 -1.3,-35.4c-0.2,-5.2 -2.6,-8.9 -6.8,-11.5c-11.7,-7.2 -24.4,-9.7 -37.8,-7.3c-5.7,1 -7.8,4.1 -7.7,9.8c0.2,6.5 0.7,13 0.8,19.5c0.4,44.4 -3.4,88.5 -10,132.3c-5.1,33.6 -11.9,66.8 -22.7,99.1c-1.8,5.3 -3.7,10.5 -5.6,15.6c-11.1,-1.4 -8.4,0 -10.4,-9.2c-0.9,-4.2 -1.4,-8.5 -2,-12.8c-6.6,-48 -8,-96.2 -5.8,-144.5c1,-21.8 2.8,-43.5 4.7,-65.2c0.5,-5.5 -0.8,-9.2 -5.9,-10.9c-6.9,-2.3 -13.8,-4.6 -20.9,-6.2c-4.5,-1.1 -8.4,0.9 -10.4,5.1c-2.6,5.6 -5.2,11.2 -6.7,17.1c-7.6,29.7 -9.8,60.1 -11.2,90.5c-1.7,37.2 -0.8,74.2 3.9,111.2c4.7,36.5 41.5,67 69,72.7c15.2,3.1 24.6,-0.4 31.5,-14.3c5.1,-10.2 9.1,-21.1 11.6,-32.2c3.5,-15.4 5,-31.2 7.4,-46.8C498.6,490.4 499.5,488.1 500.2,485.7zM344.4,521.1c-0.8,2.5 -1.2,3.5 -1.4,4.6c-2.8,17.2 -5.3,34.5 -8.4,51.7c-1,5.2 0.2,8.7 3.6,12.5C403.6,663 485,695.1 582.5,684c58,-6.6 108.2,-31.2 151.3,-70.5c5.1,-4.6 9.8,-9.7 15.1,-15c-14.7,-4.5 -25.2,-13.2 -33.4,-24.7c-26.9,31.1 -74.3,31.2 -102.2,-1.7c-30.7,26.6 -63.8,28.9 -99.4,9.9c-1.1,2 -2.1,4 -3.3,6c-16,28.6 -40.9,39.7 -72.8,31.8c-27.1,-6.7 -48.9,-22 -67,-42.9C357.3,561.2 348.1,543.2 344.4,521.1zM730.6,206.9c-1.6,-1.4 -3.1,-2.8 -4.7,-4.2c-45.4,-38.3 -97.6,-60.3 -156.9,-65c-50.5,-4 -98.4,5.4 -143.9,27.6c-3.2,1.6 -4.2,3.4 -3.9,6.9c0.3,3.7 0.3,7.7 -1.1,11c-4.4,10.6 -10.1,20.6 -14.1,31.3c-4.7,12.7 -7.9,26 -12,39.7c19,-1 35.7,3.8 51.4,12.9c3.2,-25.5 21,-37 38.1,-39.9c19.7,-3.4 38.5,0 56.2,9.1c17.1,8.7 27.5,22.3 28.5,42c0.6,11.6 1.3,23.3 1.4,34.9c0.4,30.3 0.5,60.6 0.7,90.9c0,7.4 0,14.8 0,22.7c4.6,-1.1 8.8,0.2 8.4,-5.9c-0.8,-12.1 -1.3,-24.3 -1.4,-36.4c-0.3,-40.5 0.3,-81 6,-121.1c1.8,-12.6 4.7,-25.2 9.1,-37.1c5.7,-15.4 17.8,-24.5 34.7,-24.9c9.5,-0.2 19.5,0.3 28.6,2.6c10,2.5 19.3,7.6 29.7,11.9C698.4,207.8 714,207 730.6,206.9z"/>
+</vector>
diff --git a/res/drawable/item_bg.xml b/res/drawable/item_bg.xml
new file mode 100644
index 0000000..d518cbf
--- /dev/null
+++ b/res/drawable/item_bg.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@color/navigation_accent_enabled" android:state_checked="true" />
+    <item android:color="@color/navigation_accent_disabled" />
+</selector>
diff --git a/res/drawable/more.xml b/res/drawable/more.xml
new file mode 100644
index 0000000..d33979f
--- /dev/null
+++ b/res/drawable/more.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2c0,1.1 0.9,2 2,2c1.1,0 2,-0.9 2,-2C14,10.9 13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/more2.xml b/res/drawable/more2.xml
new file mode 100644
index 0000000..8675d8f
--- /dev/null
+++ b/res/drawable/more2.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="36dp"
+        android:height="36dp"
+        android:viewportWidth="36.0"
+        android:viewportHeight="36.0">
+    <path
+        android:pathData="M18,13c1.381,0 2.5,-1.119 2.5,-2.5S19.381,8 18,8s-2.5,1.119 -2.5,2.5S16.619,13 18,13zM18,15.5c-1.381,0 -2.5,1.119 -2.5,2.5s1.119,2.5 2.5,2.5s2.5,-1.119 2.5,-2.5S19.381,15.5 18,15.5zM18,23c-1.381,0 -2.5,1.119 -2.5,2.5S16.619,28 18,28s2.5,-1.119 2.5,-2.5S19.381,23 18,23z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/multiselect.xml b/res/drawable/multiselect.xml
new file mode 100644
index 0000000..053507d
--- /dev/null
+++ b/res/drawable/multiselect.xml
@@ -0,0 +1,41 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10c5.52,0 10,-4.48 10,-10C22,6.48 17.52,2 12,2z"
+        android:fillColor="#2196F3"/>
+    <path
+        android:pathData="M10,17l-5,-5l1.4099998,-1.4099998l3.5900002,3.58l7.59,-7.59l1.4099998,1.4200001z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/multiselect_delete.xml b/res/drawable/multiselect_delete.xml
new file mode 100644
index 0000000..b3faf7b
--- /dev/null
+++ b/res/drawable/multiselect_delete.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="72.0"
+    android:viewportHeight="72.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M59,10L46.92,10l-2.16,-4L27,6l-2.16,4L13,10a1,1 0,0 0,-1 1v4a1,1 0,0 0,1 1h46a1,1 0,0 0,1 -1L60,11A1,1 0,0 0,59 10ZM16,60a6,6 0,0 0,6 6h28a6,6 0,0 0,6 -6L56,20L16,20v40Z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/multiselect_more.xml b/res/drawable/multiselect_more.xml
new file mode 100644
index 0000000..a8a23de
--- /dev/null
+++ b/res/drawable/multiselect_more.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2c0,1.1 0.9,2 2,2c1.1,0 2,-0.9 2,-2C14,10.9 13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/multiselect_share.xml b/res/drawable/multiselect_share.xml
new file mode 100644
index 0000000..5c265c0
--- /dev/null
+++ b/res/drawable/multiselect_share.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="72.0"
+    android:viewportHeight="72.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M54,48c-2.4,0 -4.5,0.9 -6.1,2.4L26.7,38.3c0.2,-0.8 0.3,-1.5 0.3,-2.4c0,-0.8 -0.1,-1.6 -0.3,-2.4l21.2,-12.1c1.6,1.7 3.7,2.6 6.1,2.6c5,0 9,-4 9,-9s-4,-9 -9,-9s-9,4 -9,9c0,0.8 0.1,1.6 0.3,2.3L24.1,29.4C22.5,27.9 20.4,27 18,27c-5,0 -9,4 -9,9s4,9 9,9c2.4,0 4.5,-0.9 6.1,-2.4l21.2,12.1C45.1,55.4 45,56.2 45,57c0,5 4,9 9,9s9,-4 9,-9S59,48 54,48z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/multiselected_back.xml b/res/drawable/multiselected_back.xml
new file mode 100644
index 0000000..0e237bf
--- /dev/null
+++ b/res/drawable/multiselected_back.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8l8,8l1.41,-1.41L7.83,13H20V11z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/overflow.xml b/res/drawable/overflow.xml
new file mode 100644
index 0000000..15d6b53
--- /dev/null
+++ b/res/drawable/overflow.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+
+    <path
+        android:pathData="M0,0h24v24H0V0z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M12,8c1.1,0,2-0.9,2-2s-0.9-2-2-2c-1.1,0-2,0.9-2,2S10.9,8,12,8z
+M12,10c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2 c1.1,0,2-0.9,2-2C14,10.9,13.1,10,12,10z
+M12,16c-1.1,0-2,0.9-2,2s0.9,2,2,2c1.1,0,2-0.9,2-2S13.1,16,12,16z" />
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ref_city.png b/res/drawable/ref_city.png
new file mode 100644
index 0000000..0059216
--- /dev/null
+++ b/res/drawable/ref_city.png
Binary files differ
diff --git a/res/drawable/ref_flowers.png b/res/drawable/ref_flowers.png
new file mode 100644
index 0000000..22c1162
--- /dev/null
+++ b/res/drawable/ref_flowers.png
Binary files differ
diff --git a/res/drawable/seestraight.xml b/res/drawable/seestraight.xml
new file mode 100644
index 0000000..317fa4e
--- /dev/null
+++ b/res/drawable/seestraight.xml
@@ -0,0 +1,62 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 7.2 23.3 L 5.5 23.3 L 5.5 7.1 L 13.3 4.8 L 14.1 4.8 L 21.7 7.1 L 21.7 11.9 L 20 11.9 L 20 8.3 L 13.7 6.5 L 13.4 6.5 L 7.2 8.3 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 8.6 7 L 8 7 L 8 5.3 L 13.5 3.5 L 19.1 5.3 L 19.1 7 L 18.6 7 L 18.6 5.7 L 13.5 4.1 L 8.6 5.7 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 13.4 3.8 H 13.7 V 5.6 H 13.4 V 3.8 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 13 23.3 L 12.7 23.3 L 12.7 8.4 L 6.5 10.2 L 6.5 9.9 L 13 8.1 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 14.4 23.3 L 14.1 23.3 L 14.1 8 L 20.7 9.8 L 20.6 10.1 L 14.4 8.3 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M29.8,27h-1.7v-1.4h1.7V27z M26.3,27h-1.8v-1.4h1.8V27z M22.6,27h-1.8v-1.4h1.8V27z
+M18.9,27h-1.8v-1.4 h1.8V27z M15.3,27h-1.8v-1.4h1.8V27z M11.6,27H9.8v-1.4h1.8V27z
+M8,27H6.2v-1.4H8V27z M4.3,27H2.5v-1.4h1.8V27z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 26.7 23.3 L 25 23.3 L 25 13.4 L 22.3 12.3 L 19.6 13.4 L 19.6 23.3 L 17.8 23.3 L 17.8 12.2 L 22 10.6 L 22.6 10.6 L 26.7 12.2 Z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M 22.2 11.6 H 22.5 V 23.3 H 22.2 V 11.6 Z" />
+</vector>
diff --git a/res/drawable/selected.xml b/res/drawable/selected.xml
new file mode 100644
index 0000000..f55e66d
--- /dev/null
+++ b/res/drawable/selected.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="37dp"
+        android:height="37dp"
+        android:viewportWidth="37.0"
+        android:viewportHeight="37.0">
+    <path
+        android:pathData="M36,1v35H1V1H36M37,0H0v37h37V0L37,0z"
+        android:fillColor="#40C4FF"/>
+</vector>
diff --git a/res/drawable/share.xml b/res/drawable/share.xml
new file mode 100644
index 0000000..0ce3de8
--- /dev/null
+++ b/res/drawable/share.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M17.999,16.121c-0.76,0 -1.439,0.3 -1.96,0.77L8.91,12.741C8.959,12.512 9,12.281 9,12.041s-0.04,-0.471 -0.09,-0.7l7.049,-4.11c0.54,0.5 1.25,0.81 2.04,0.81c1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3s-3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.851C7.5,9.351 6.79,9.041 6,9.041c-1.66,0 -3,1.34 -3,3c0,1.661 1.34,3 3,3c0.79,0 1.5,-0.311 2.04,-0.811l7.12,4.16c-0.051,0.211 -0.08,0.43 -0.08,0.65c0,1.609 1.311,2.92 2.92,2.92s2.92,-1.311 2.92,-2.92S19.608,16.121 17.999,16.121z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/sliderbg.xml b/res/drawable/sliderbg.xml
new file mode 100644
index 0000000..204c925
--- /dev/null
+++ b/res/drawable/sliderbg.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="216dp"
+        android:height="4dp"
+        android:viewportWidth="216.0"
+        android:viewportHeight="4.0">
+    <path
+        android:pathData="M0,1h216v2h-216z"
+        android:fillAlpha="0.2"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/sliderprogress.xml b/res/drawable/sliderprogress.xml
new file mode 100644
index 0000000..5c2b541
--- /dev/null
+++ b/res/drawable/sliderprogress.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="216dp"
+        android:height="4dp"
+        android:viewportWidth="216.0"
+        android:viewportHeight="4.0">
+    <path
+        android:pathData="M0,1h216v2h-216z"
+        android:fillColor="#4f92e9"/>
+</vector>
diff --git a/res/drawable/slideshow.xml b/res/drawable/slideshow.xml
new file mode 100644
index 0000000..dfe8c9c
--- /dev/null
+++ b/res/drawable/slideshow.xml
@@ -0,0 +1,38 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M10,8v8l5,-4L10,8zM19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zM19,19H5V5h14V19z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/res/drawable/spinner_triangle.xml b/res/drawable/spinner_triangle.xml
new file mode 100644
index 0000000..1000059
--- /dev/null
+++ b/res/drawable/spinner_triangle.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector android:autoMirrored="true" android:height="12dp"
+    android:viewportHeight="12.0" android:viewportWidth="12.0"
+    android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillAlpha="0.3" android:fillColor="@color/white" android:pathData="M12,3.7V12H3.7L12,3.7z"/>
+</vector>
diff --git a/res/drawable/switch_inner_holo_dark.xml b/res/drawable/switch_inner_holo_dark.xml
deleted file mode 100644
index c0b00bb..0000000
--- a/res/drawable/switch_inner_holo_dark.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="false" android:drawable="@drawable/switch_thumb_disabled_holo_dark" />
-    <item android:state_pressed="true"  android:drawable="@drawable/switch_thumb_pressed_holo_dark" />
-    <item android:state_checked="true"  android:drawable="@drawable/switch_thumb_activated_holo_dark" />
-    <item                               android:drawable="@drawable/switch_thumb_holo_dark" />
-</selector>
diff --git a/res/drawable/timeline.xml b/res/drawable/timeline.xml
new file mode 100644
index 0000000..8d6dc37
--- /dev/null
+++ b/res/drawable/timeline.xml
@@ -0,0 +1,43 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M19.057,4.034h-1.01V2.059h-2.016v1.976H7.969V2.059H5.951v1.976H4.902c-1.115,0 -1.967,0.943 -1.967,2.058l-0.01,13.832c0,1.114 0.902,2.017 2.016,2.017h14.115c1.113,0 2.016,-0.902 2.016,-2.017V6.092C21.072,4.978 20.17,4.034 19.057,4.034zM19.098,19.965H4.941V9.015h14.156V19.965z"
+        android:fillAlpha="0.54"/>
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M6.184,16.241l3.738,-4.984l2.908,3.742l2.076,-2.496l2.907,3.738H6.184z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/tp_bg_select.xml b/res/drawable/tp_bg_select.xml
new file mode 100644
index 0000000..bc30177
--- /dev/null
+++ b/res/drawable/tp_bg_select.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/btn_tp_sel_bg" android:state_selected="false"></item>
+    <item android:drawable="@drawable/btn_tp_sel_bg_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_brush_large.xml b/res/drawable/tp_brush_large.xml
new file mode 100644
index 0000000..3277b93
--- /dev/null
+++ b/res/drawable/tp_brush_large.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_brush_size_large" android:state_selected="false"></item>
+    <item android:drawable="@drawable/ic_brush_size_large_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_brush_med.xml b/res/drawable/tp_brush_med.xml
new file mode 100644
index 0000000..fceff8b
--- /dev/null
+++ b/res/drawable/tp_brush_med.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_brush_size_med" android:state_selected="false"></item>
+    <item android:drawable="@drawable/ic_brush_size_med_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_brush_sm.xml b/res/drawable/tp_brush_sm.xml
new file mode 100644
index 0000000..88de168
--- /dev/null
+++ b/res/drawable/tp_brush_sm.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/ic_brush_size_sm" android:state_selected="false"></item>
+    <item android:drawable="@drawable/ic_brush_size_sm_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_help.xml b/res/drawable/tp_help.xml
new file mode 100644
index 0000000..07a126e
--- /dev/null
+++ b/res/drawable/tp_help.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/btn_tp_help" android:state_selected="false"></item>
+    <item android:drawable="@drawable/btn_tp_help_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_mask_toggle.xml b/res/drawable/tp_mask_toggle.xml
new file mode 100644
index 0000000..29abd41
--- /dev/null
+++ b/res/drawable/tp_mask_toggle.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@android:color/holo_blue_light" android:state_checked="true"></item>
+    <item android:drawable="@color/cache_placeholder" android:state_checked="false"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_touch_up.xml b/res/drawable/tp_touch_up.xml
new file mode 100644
index 0000000..b8c1a94
--- /dev/null
+++ b/res/drawable/tp_touch_up.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/btn_tp_touchup" android:state_selected="false"></item>
+    <item android:drawable="@drawable/btn_tp_touchup_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/tp_undo.xml b/res/drawable/tp_undo.xml
new file mode 100644
index 0000000..146d5b8
--- /dev/null
+++ b/res/drawable/tp_undo.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/btn_tp_undo_disabled" android:state_enabled="false"></item>
+    <item android:drawable="@drawable/btn_tp_undo" android:state_selected="false"></item>
+    <item android:drawable="@drawable/btn_tp_undo_sel" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/trueportrait_background.xml b/res/drawable/trueportrait_background.xml
new file mode 100644
index 0000000..b209b84
--- /dev/null
+++ b/res/drawable/trueportrait_background.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/trueportrait_disabled" android:state_enabled="false"></item>
+    <item android:drawable="@drawable/trueportrait" android:state_selected="false"></item>
+    <item android:drawable="@drawable/trueportrait_select" android:state_selected="true"></item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/truescanner.xml b/res/drawable/truescanner.xml
new file mode 100644
index 0000000..c79f585
--- /dev/null
+++ b/res/drawable/truescanner.xml
@@ -0,0 +1,63 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M15.1,23.4c0,0.8,0,1.6,0,2.3c-4,0-7.9,0-11.9,0c0-6.7,0-13.4,0-20c4,0,7.9,0,11.9,0c0,0.8,0,1.5,0,2.3
+c-3.2,0-6.4,0-9.6,0c0,5.1,0,10.2,0,15.4C8.7,23.4,11.9,23.4,15.1,23.4z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M15.1,10c0,0,0,0.1,0,0.1c0,1.9,0,3.7,0,5.6c0,0.1,0,0.2-0.1,0.3c-0.1,0.2-0.2,0.4-0.3,0.6c0,0,0,0.1,0,0.1
+c0.1,0,0.3,0,0.4,0c0,0.8,0,1.5,0,2.2c-0.1,0-0.2,0-0.3,0c-0.3,0-0.7,0-1,0c-0.1,0-0.1,0-0.2,0.1c-0.4,0.8-0.7,1.6-1.1,2.4
+c0,0.1-0.1,0.1-0.1,0.1c-0.9,0-1.8,0-2.8,0c0,0,0,0-0.1,0C11.4,17.7,13.2,13.9,15.1,10C15.1,10,15.1,10,15.1,10z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M17,16.4c0,4.2,0,8.4,0,12.5c0,0.3-0.2,0.5-0.4,0.5c-0.3,0-0.5-0.2-0.5-0.4c0,0,0-0.1,0-0.1
+c0-8.3,0-16.7,0-25c0-0.1,0-0.2,0-0.2c0.1-0.2,0.3-0.4,0.5-0.3c0.2,0,0.4,0.2,0.4,0.5c0,0,0,0.1,0,0.1C17,8.1,17,12.3,17,16.4z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M28.7,6.5c0,6.1,0,12.2,0,18.3c-3.4,0-6.9,0-10.3,0c0-0.1,0-0.2,0-0.3c3.3,0,6.7,0,10,0
+c0-5.9,0-11.8,0-17.7c-3.3,0-6.6,0-9.9,0c0-0.1,0-0.2,0-0.3C21.9,6.5,25.3,6.5,28.7,6.5z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M18,9.6c1.9,4,3.8,8,5.7,12.1c-0.1,0-0.1,0-0.1,0c-1,0-2,0-3,0c-0.1,0-0.1,0-0.2-0.1
+c-0.4-0.8-0.7-1.6-1.1-2.4c0-0.1-0.1-0.1-0.2-0.1c-0.3,0-0.7,0-1,0c0,0-0.1,0-0.1,0c0-0.1,0-0.2,0-0.3c0,0,0.1,0,0.1,0
+c0.4,0,0.9,0,1.3,0c0.1,0,0.1,0,0.2,0.1c0.4,0.8,0.7,1.6,1.1,2.4c0,0.1,0.1,0.1,0.2,0.1c0.8,0,1.5,0,2.3,0c0,0,0.1,0,0.1,0
+c-0.1-0.2-0.2-0.5-0.3-0.7c-1.6-3.3-3.1-6.6-4.7-9.9c0,0,0-0.1,0-0.1C17.9,10.4,17.9,10,18,9.6C18,9.7,18,9.6,18,9.6
+C18,9.6,18,9.6,18,9.6z" />
+    <path
+        android:fillColor="@color/white"
+        android:pathData="M18.6,16.8c-0.2,0-0.4,0-0.6,0c0-0.1,0-0.2,0-0.3c0,0,0.1,0,0.1,0c-0.2-0.3-0.1-0.7-0.1-1
+C18.2,15.9,18.4,16.4,18.6,16.8z" />
+</vector>
diff --git a/res/drawable/truescanner_background.xml b/res/drawable/truescanner_background.xml
new file mode 100644
index 0000000..381bd7f
--- /dev/null
+++ b/res/drawable/truescanner_background.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/truescanner" android:state_selected="false"/>
+    <item android:drawable="@drawable/truescanner_select" android:state_selected="true"/>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/truescanner_select.xml b/res/drawable/truescanner_select.xml
new file mode 100644
index 0000000..382c14e
--- /dev/null
+++ b/res/drawable/truescanner_select.xml
@@ -0,0 +1,63 @@
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="32dp"
+    android:height="32dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M15.1,23.4c0,0.8,0,1.6,0,2.3c-4,0-7.9,0-11.9,0c0-6.7,0-13.4,0-20c4,0,7.9,0,11.9,0c0,0.8,0,1.5,0,2.3
+c-3.2,0-6.4,0-9.6,0c0,5.1,0,10.2,0,15.4C8.7,23.4,11.9,23.4,15.1,23.4z" />
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M15.1,10c0,0,0,0.1,0,0.1c0,1.9,0,3.7,0,5.6c0,0.1,0,0.2-0.1,0.3c-0.1,0.2-0.2,0.4-0.3,0.6c0,0,0,0.1,0,0.1
+c0.1,0,0.3,0,0.4,0c0,0.8,0,1.5,0,2.2c-0.1,0-0.2,0-0.3,0c-0.3,0-0.7,0-1,0c-0.1,0-0.1,0-0.2,0.1c-0.4,0.8-0.7,1.6-1.1,2.4
+c0,0.1-0.1,0.1-0.1,0.1c-0.9,0-1.8,0-2.8,0c0,0,0,0-0.1,0C11.4,17.7,13.2,13.9,15.1,10C15.1,10,15.1,10,15.1,10z" />
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M17,16.4c0,4.2,0,8.4,0,12.5c0,0.3-0.2,0.5-0.4,0.5c-0.3,0-0.5-0.2-0.5-0.4c0,0,0-0.1,0-0.1
+c0-8.3,0-16.7,0-25c0-0.1,0-0.2,0-0.2c0.1-0.2,0.3-0.4,0.5-0.3c0.2,0,0.4,0.2,0.4,0.5c0,0,0,0.1,0,0.1C17,8.1,17,12.3,17,16.4z" />
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M28.7,6.5c0,6.1,0,12.2,0,18.3c-3.4,0-6.9,0-10.3,0c0-0.1,0-0.2,0-0.3c3.3,0,6.7,0,10,0
+c0-5.9,0-11.8,0-17.7c-3.3,0-6.6,0-9.9,0c0-0.1,0-0.2,0-0.3C21.9,6.5,25.3,6.5,28.7,6.5z" />
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M18,9.6c1.9,4,3.8,8,5.7,12.1c-0.1,0-0.1,0-0.1,0c-1,0-2,0-3,0c-0.1,0-0.1,0-0.2-0.1
+c-0.4-0.8-0.7-1.6-1.1-2.4c0-0.1-0.1-0.1-0.2-0.1c-0.3,0-0.7,0-1,0c0,0-0.1,0-0.1,0c0-0.1,0-0.2,0-0.3c0,0,0.1,0,0.1,0
+c0.4,0,0.9,0,1.3,0c0.1,0,0.1,0,0.2,0.1c0.4,0.8,0.7,1.6,1.1,2.4c0,0.1,0.1,0.1,0.2,0.1c0.8,0,1.5,0,2.3,0c0,0,0.1,0,0.1,0
+c-0.1-0.2-0.2-0.5-0.3-0.7c-1.6-3.3-3.1-6.6-4.7-9.9c0,0,0-0.1,0-0.1C17.9,10.4,17.9,10,18,9.6C18,9.7,18,9.6,18,9.6
+C18,9.6,18,9.6,18,9.6z" />
+    <path
+        android:fillColor="#FF4F92E9"
+        android:pathData="M18.6,16.8c-0.2,0-0.4,0-0.6,0c0-0.1,0-0.2,0-0.3c0,0,0.1,0,0.1,0c-0.2-0.3-0.1-0.7-0.1-1
+C18.2,15.9,18.4,16.4,18.6,16.8z" />
+</vector>
diff --git a/res/drawable/videoplayer_pause.xml b/res/drawable/videoplayer_pause.xml
new file mode 100644
index 0000000..39a4361
--- /dev/null
+++ b/res/drawable/videoplayer_pause.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_vidcontrol_pause" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_vidcontrol_disable_pause" />
+</selector>
diff --git a/res/drawable/videoplayer_play.xml b/res/drawable/videoplayer_play.xml
new file mode 100644
index 0000000..be78a7b
--- /dev/null
+++ b/res/drawable/videoplayer_play.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_vidcontrol_play" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_vidcontrol_disable_play" />
+</selector>
diff --git a/res/drawable/videoplayer_reload.xml b/res/drawable/videoplayer_reload.xml
new file mode 100644
index 0000000..b5d48bf
--- /dev/null
+++ b/res/drawable/videoplayer_reload.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/ic_vidcontrol_reload" />
+    <item android:state_enabled="false"
+        android:drawable="@drawable/ic_vidcontrol_disable_reload" />
+</selector>
diff --git a/res/drawable/videos.xml b/res/drawable/videos.xml
new file mode 100644
index 0000000..406d41d
--- /dev/null
+++ b/res/drawable/videos.xml
@@ -0,0 +1,39 @@
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/black"
+        android:pathData="M3.999,6h-2v14c0,1.1 0.9,2 2,2h14v-2h-14V6zM19.999,2h-12c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4C21.999,2.9 21.099,2 19.999,2zM11.999,14.5v-9l6,4.5L11.999,14.5z"
+        android:fillAlpha="0.54"/>
+</vector>
diff --git a/res/drawable/watermark.xml b/res/drawable/watermark.xml
new file mode 100644
index 0000000..5383d5c
--- /dev/null
+++ b/res/drawable/watermark.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/ic_watermark_selected"/>
+    <item android:state_selected="false" android:drawable="@drawable/ic_watermark"/>
+</selector>
\ No newline at end of file
diff --git a/res/layout-land/camera_controls.xml b/res/layout-land/camera_controls.xml
index d177240..4baf23e 100644
--- a/res/layout-land/camera_controls.xml
+++ b/res/layout-land/camera_controls.xml
@@ -24,13 +24,13 @@
             android:clickable="true"
             android:layout_height="match_parent"
             android:layout_width="@dimen/switcher_size"
-            android:layout_gravity="right" />
+            android:layout_gravity="end" />
 
         <include layout="@layout/menu_indicators"
             android:layout_width="64dip"
             android:layout_height="64dip"
             android:layout_marginTop="-5dip"
-            android:layout_marginRight="6dip"
+            android:layout_marginEnd="6dip"
             android:layout_gravity="top|right"/>
 
         <com.android.camera.ui.PieMenuButton
@@ -38,13 +38,13 @@
             style="@style/SwitcherButton"
             android:contentDescription="@string/accessibility_menu_button"
             android:layout_gravity="right|top"
-            android:layout_marginRight="2dip" />
+            android:layout_marginEnd="2dip" />
 
         <com.android.camera.ui.CameraSwitcher
             android:id="@+id/camera_switcher"
             style="@style/SwitcherButton"
             android:layout_gravity="right|bottom"
-            android:layout_marginRight="2dip"
+            android:layout_marginEnd="2dip"
             android:contentDescription="@string/accessibility_mode_picker" />
 
         <com.android.camera.ShutterButton
@@ -52,7 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="right|center_vertical"
-            android:layout_marginRight="@dimen/shutter_offset"
+            android:layout_marginEnd="@dimen/shutter_offset"
             android:clickable="true"
             android:contentDescription="@string/accessibility_shutter_button"
             android:focusable="true"
diff --git a/res/layout-land/filtershow_activity.xml b/res/layout-land/filtershow_activity.xml
deleted file mode 100644
index f438012..0000000
--- a/res/layout-land/filtershow_activity.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:id="@+id/mainView"
-             android:background="@drawable/filtershow_tiled_background">
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="horizontal"
-            android:animateLayoutChanges="true">
-
-
-        <FrameLayout
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_weight="1">
-
-            <ProgressBar
-                    android:id="@+id/loading"
-                    style="@android:style/Widget.Holo.ProgressBar.Large"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:indeterminate="true"
-                    android:indeterminateOnly="true"
-                    android:background="@null"/>
-
-            <LinearLayout
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="vertical"
-                    >
-
-                <LinearLayout
-                        android:layout_weight="1"
-                        android:layout_width="wrap_content"
-                        android:layout_height="0dp"
-                        android:orientation="horizontal">
-
-                    <FrameLayout
-                            android:id="@+id/central_panel_container"
-                            android:layout_gravity="center"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_weight="1"
-                            android:visibility="gone"/>
-
-                    <FrameLayout
-                            android:id="@+id/editorContainer"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_weight="1"/>
-
-                    <com.android.gallery3d.filtershow.imageshow.ImageShow
-                            android:id="@+id/imageShow"
-                            android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
-                            android:layout_weight="1"/>
-
-                </LinearLayout>
-
-                <FrameLayout
-                        android:id="@+id/state_panel_container"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:visibility="visible"/>
-
-            </LinearLayout>
-
-        </FrameLayout>
-
-        <LinearLayout
-                android:id="@+id/mainPanel"
-                android:layout_width="350dip"
-                android:layout_height="match_parent"
-                android:orientation="vertical"
-                android:animateLayoutChanges="true">
-
-            <FrameLayout
-                    android:id="@+id/main_panel_container"
-                    android:layout_width="350dip"
-                    android:layout_height="0dip"
-                    android:layout_weight="1"/>
-
-        </LinearLayout>
-
-    </LinearLayout>
-
-    <com.android.gallery3d.filtershow.category.CategorySelected
-            android:layout_width="@dimen/category_panel_icon_size"
-            android:layout_height="@dimen/category_panel_icon_size"
-            android:id="@+id/categorySelectedIndicator"
-            android:visibility="invisible"/>
-
-</FrameLayout>
diff --git a/res/layout-land/filtershow_category_panel_new.xml b/res/layout-land/filtershow_category_panel_new.xml
deleted file mode 100644
index ad85f71..0000000
--- a/res/layout-land/filtershow_category_panel_new.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-
-    <com.android.gallery3d.filtershow.category.IconView
-            android:id="@+id/addButton"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/category_panel_height"
-            android:src="@drawable/filtershow_add"/>
-
-    <ListView
-            android:id="@+id/listItems"
-            android:orientation="vertical"
-            android:layout_width="match_parent"
-            android:layout_height="0dp"
-            android:layout_margin="8dip"
-            android:divider="@android:color/transparent"
-            android:dividerHeight="8dip"
-            android:layout_weight="1"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/filtershow_color_border_ui.xml b/res/layout-land/filtershow_color_border_ui.xml
index 9945d9d..82fe14a 100644
--- a/res/layout-land/filtershow_color_border_ui.xml
+++ b/res/layout-land/filtershow_color_border_ui.xml
@@ -46,14 +46,14 @@
 
                 <TextView
                         android:id="@+id/controlName1"
-                        android:layout_gravity="left"
-                        android:layout_marginLeft="8dip"
+                        android:layout_gravity="start"
+                        android:layout_marginStart="8dip"
                         android:text="@string/color_border_size"/>
 
                 <TextView
                         android:id="@+id/colorBorderSizeValue"
-                        android:layout_gravity="right"
-                        android:layout_marginRight="8dip"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="8dip"
                         android:textStyle="bold"/>
 
                 <SeekBar
@@ -74,14 +74,14 @@
 
                 <TextView
                         android:id="@+id/controlName2"
-                        android:layout_gravity="left"
-                        android:layout_marginLeft="8dip"
+                        android:layout_gravity="start"
+                        android:layout_marginStart="8dip"
                         android:text="@string/color_border_corner_size"/>
 
                 <TextView
                         android:id="@+id/colorBorderCornerValue"
-                        android:layout_gravity="right"
-                        android:layout_marginRight="8dip"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="8dip"
                         android:textStyle="bold"/>
 
                 <SeekBar
@@ -122,7 +122,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/draw_color"
-                    android:layout_marginLeft="8dip"
+                    android:layout_marginStart="8dip"
                     android:id="@+id/textView"/>
 
 
@@ -130,8 +130,8 @@
                     android:id="@+id/btnSelect"
                     android:layout_width="match_parent"
                     android:layout_height="32dp"
-                    android:layout_marginLeft="18dp"
-                    android:layout_marginRight="18dp"
+                    android:layout_marginStart="18dp"
+                    android:layout_marginEnd="18dp"
                     android:layout_marginTop="0dp"
                     android:layout_marginBottom="0dp"
                     />
@@ -142,7 +142,7 @@
                     android:layout_height="@dimen/draw_ui_width"
                     android:layout_gravity="center"
                     android:layout_marginTop="8dp"
-                    android:layout_marginRight="1dp"/>
+                    android:layout_marginEnd="1dp"/>
 
             <com.android.gallery3d.filtershow.colorpicker.ColorHueView
                     android:id="@+id/ColorHueView"
@@ -164,8 +164,8 @@
             android:orientation="horizontal"
             android:layout_marginBottom="10dp"
             android:layout_marginTop="10dp"
-            android:layout_marginLeft="1dp"
-            android:layout_marginRight="1dp">
+            android:layout_marginStart="1dp"
+            android:layout_marginEnd="1dp">
 
         <LinearLayout
                 android:layout_width="match_parent"
@@ -173,8 +173,8 @@
                 android:orientation="horizontal"
                 android:layout_marginBottom="10dp"
                 android:layout_marginTop="10dp"
-                android:layout_marginLeft="1dp"
-                android:layout_marginRight="1dp">
+                android:layout_marginStart="1dp"
+                android:layout_marginEnd="1dp">
 
             <LinearLayout
                     android:id="@+id/listColors"
@@ -189,7 +189,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button02"
@@ -197,7 +197,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button03"
@@ -205,7 +205,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button04"
@@ -213,7 +213,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button05"
@@ -221,7 +221,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
             </LinearLayout>
             <FrameLayout
diff --git a/res/layout-land/filtershow_draw_ui.xml b/res/layout-land/filtershow_draw_ui.xml
index 5e0a327..642a7bd 100644
--- a/res/layout-land/filtershow_draw_ui.xml
+++ b/res/layout-land/filtershow_draw_ui.xml
@@ -55,14 +55,14 @@
 
                 <TextView
                         android:id="@+id/controlName1"
-                        android:layout_gravity="left"
-                        android:layout_marginLeft="8dip"
+                        android:layout_gravity="start"
+                        android:layout_marginStart="8dip"
                         android:text="@string/draw_size"/>
 
                 <TextView
                         android:id="@+id/drawSizeValue"
-                        android:layout_gravity="right"
-                        android:layout_marginRight="8dip"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="8dip"
                         android:textStyle="bold"/>
 
                 <SeekBar
@@ -106,7 +106,7 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:text="@string/draw_color"
-                    android:layout_marginLeft="8dip"
+                    android:layout_marginStart="8dip"
                     android:id="@+id/textView"
                     android:visibility="gone"/>
 
@@ -114,8 +114,8 @@
                     android:id="@+id/btnSelect"
                     android:layout_width="match_parent"
                     android:layout_height="32dp"
-                    android:layout_marginLeft="18dp"
-                    android:layout_marginRight="18dp"
+                    android:layout_marginStart="18dp"
+                    android:layout_marginEnd="18dp"
                     android:layout_marginTop="0dp"
                     android:layout_marginBottom="0dp"
                     />
@@ -126,7 +126,7 @@
                     android:layout_height="@dimen/draw_ui_width"
                     android:layout_gravity="center"
                     android:layout_marginTop="8dp"
-                    android:layout_marginRight="1dp"/>
+                    android:layout_marginEnd="1dp"/>
 
             <com.android.gallery3d.filtershow.colorpicker.ColorHueView
                     android:id="@+id/ColorHueView"
@@ -149,8 +149,8 @@
             android:orientation="horizontal"
             android:layout_marginBottom="10dp"
             android:layout_marginTop="10dp"
-            android:layout_marginLeft="1dp"
-            android:layout_marginRight="1dp">
+            android:layout_marginStart="1dp"
+            android:layout_marginEnd="1dp">
 
 
             <LinearLayout
@@ -166,7 +166,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button02"
@@ -174,7 +174,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button03"
@@ -182,7 +182,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button04"
@@ -190,7 +190,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
                 <Button
                         android:id="@+id/draw_color_button05"
@@ -198,7 +198,7 @@
                         android:layout_weight="1"
                         android:layout_height="wrap_content"
                         android:background="@drawable/filtershow_color_picker_circle"
-                        android:layout_marginRight="4dp"/>
+                        android:layout_marginEnd="4dp"/>
 
             </LinearLayout>
 
diff --git a/res/layout-land/filtershow_editor_panel.xml b/res/layout-land/filtershow_editor_panel.xml
deleted file mode 100644
index f51dc14..0000000
--- a/res/layout-land/filtershow_editor_panel.xml
+++ /dev/null
@@ -1,139 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/top"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:orientation="vertical"
-              android:visibility="visible">
-
-    <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            >
-
-        <Button
-                android:id="@+id/toggle_state"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/imageState"
-                android:background="@color/background_main_toolbar"
-                android:layout_alignParentTop="true"
-                />
-
-        <View
-                android:id="@+id/bottomControlLineBottom"
-                android:background="@color/toolbar_separation_line"
-                android:layout_height="1dip"
-                android:layout_width="match_parent"
-                android:layout_alignParentBottom="true"
-                />
-        <LinearLayout
-                android:id="@+id/applyBar"
-                android:layout_width="match_parent"
-                android:layout_height="48dip"
-                android:background="@color/background_main_toolbar"
-                android:orientation="horizontal"
-                android:baselineAligned="false"
-                android:visibility="visible"
-                android:layout_above="@id/bottomControlLineBottom"
-                >
-
-            <ImageButton
-                    android:id="@+id/cancelFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="left|center_vertical"
-                    android:background="@android:color/transparent"
-                    android:layout_weight=".1"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_cancel_holo_light"
-                    android:textSize="18dip"/>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <LinearLayout
-                    android:id="@+id/panelAccessoryViewList"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="horizontal"
-                    android:visibility="visible">
-
-                <com.android.gallery3d.filtershow.editors.SwapButton
-                        android:id="@+id/applyEffect"
-                        android:layout_width="fill_parent"
-                        android:layout_height="fill_parent"
-                        android:layout_gravity="center"
-                        android:background="@android:color/transparent"
-                        android:text="@string/apply_effect"
-                        android:textSize="18dip"
-                        android:drawableEnd="@drawable/filtershow_menu_marker_rtl"
-                        android:textAllCaps="true"/>
-
-            </LinearLayout>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <ImageButton
-                    android:id="@+id/applyFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="right|center_vertical"
-                    android:layout_weight=".1"
-                    android:background="@android:color/transparent"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_done_holo_light"
-                    android:textSize="18dip"/>
-        </LinearLayout>
-        <View
-                android:id="@+id/bottomControlLineTop"
-                android:background="@color/toolbar_separation_line"
-                android:layout_height="1dip"
-                android:layout_width="match_parent"
-                android:layout_above="@id/applyBar"
-                />
-
-        <LinearLayout
-                android:id="@+id/controlArea"
-                android:layout_width="match_parent"
-                android:layout_height="fill_parent"
-                android:orientation="vertical"
-                android:layout_above="@id/bottomControlLineTop"
-                android:layout_below="@id/toggle_state"
-                android:gravity="bottom"
-                android:visibility="visible">
-
-            <SeekBar
-                    android:id="@+id/primarySeekBar"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    style="@style/FilterShowSlider"
-                    android:visibility="gone"/>
-
-        </LinearLayout>
-
-    </RelativeLayout>
-</LinearLayout>
diff --git a/res/layout-land/filtershow_grad_ui.xml b/res/layout-land/filtershow_grad_ui.xml
index fd09bee..7cc874c 100644
--- a/res/layout-land/filtershow_grad_ui.xml
+++ b/res/layout-land/filtershow_grad_ui.xml
@@ -30,14 +30,14 @@
 
         <TextView
                 android:id="@+id/controlName1"
-                android:layout_gravity="left"
-                android:layout_marginLeft="8dip"
+                android:layout_gravity="start"
+                android:layout_marginStart="8dip"
                 android:text="@string/editor_grad_brightness" />
 
         <TextView
                 android:id="@+id/gradBrightnessValue"
-                android:layout_gravity="right"
-                android:layout_marginRight="8dip"
+                android:layout_gravity="end"
+                android:layout_marginEnd="8dip"
                 android:textStyle="bold" />
 
         <SeekBar
@@ -58,14 +58,14 @@
 
         <TextView
                 android:id="@+id/controlName2"
-                android:layout_gravity="left"
-                android:layout_marginLeft="8dip"
+                android:layout_gravity="start"
+                android:layout_marginStart="8dip"
                 android:text="@string/editor_grad_saturation"/>
 
         <TextView
                 android:id="@+id/gradSaturationValue"
-                android:layout_gravity="right"
-                android:layout_marginRight="8dip"
+                android:layout_gravity="end"
+                android:layout_marginEnd="8dip"
                 android:textStyle="bold" />
 
         <SeekBar
@@ -84,14 +84,14 @@
 
         <TextView
                 android:id="@+id/controlName3"
-                android:layout_gravity="left"
-                android:layout_marginLeft="8dip"
+                android:layout_gravity="start"
+                android:layout_marginStart="8dip"
                 android:text="@string/editor_grad_contrast"/>
 
         <TextView
                 android:id="@+id/gradContrastValue"
-                android:layout_gravity="right"
-                android:layout_marginRight="8dip"
+                android:layout_gravity="end"
+                android:layout_marginEnd="8dip"
                 android:textStyle="bold" />
 
         <SeekBar
@@ -118,9 +118,9 @@
             android:scaleType="centerInside"
             android:layout_weight="0"
             android:background="@drawable/filtershow_button_background"
-            android:src="@drawable/filtershow_addpoint"
+            android:src="@drawable/addspot"
             android:paddingBottom="8dp"
-            android:layout_marginLeft="48dp" />
+            android:layout_marginStart="48dp" />
 
         <View
             android:layout_width="wrap_content"
@@ -136,9 +136,9 @@
             android:scaleType="centerInside"
             android:layout_weight="0"
             android:background="@drawable/filtershow_button_background"
-            android:src="@drawable/ic_menu_trash_holo_light"
+            android:src="@drawable/delete"
             android:paddingBottom="8dp"
-            android:layout_marginRight="48dp" />
+            android:layout_marginEnd="48dp" />
 
     </LinearLayout>
 
diff --git a/res/layout-land/filtershow_main_panel.xml b/res/layout-land/filtershow_main_panel.xml
deleted file mode 100644
index 6a36de2..0000000
--- a/res/layout-land/filtershow_main_panel.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent"
-              android:baselineAligned="false"
-              android:orientation="vertical"
-              android:animateLayoutChanges="true"
-              android:visibility="visible" >
-
-    <FrameLayout android:id="@+id/category_panel_container"
-                 android:layout_width="match_parent"
-                 android:layout_height="0dip"
-                 android:layout_weight="1"/>
-
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-    <com.android.gallery3d.filtershow.CenteredLinearLayout
-            xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-            android:layout_width="match_parent"
-            android:layout_height="48dip"
-            android:layout_gravity="center|bottom"
-            custom:max_width="400dip"
-            android:orientation="vertical">
-
-        <LinearLayout android:layout_width="wrap_content"
-                      android:layout_height="match_parent"
-                      android:background="@color/background_main_toolbar">
-
-            <ImageButton
-                    android:id="@+id/fxButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_effects"/>
-
-            <ImageButton
-                    android:id="@+id/borderButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_border"/>
-
-            <ImageButton
-                    android:id="@+id/geometryButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_fix"/>
-
-            <ImageButton
-                    android:id="@+id/colorsButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_color"/>
-
-        </LinearLayout>
-
-    </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/filtershow_presets_dialog.xml b/res/layout-land/filtershow_presets_dialog.xml
new file mode 100644
index 0000000..389eaec
--- /dev/null
+++ b/res/layout-land/filtershow_presets_dialog.xml
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="424dp"
+    android:layout_height="260dp"
+    android:background="#EFEFEF">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="22dp"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/icon_tools"
+            android:layout_width="21dp"
+            android:layout_height="27dp"
+            android:src="@drawable/icon_tools"/>
+
+        <TextView
+            android:id="@+id/dialog_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingStart="8dp"
+            android:textColor="#000000"
+            android:textSize="16sp"
+            android:text="@string/filtershow_dialog_title"/>
+    </LinearLayout>
+
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:layout_marginTop="20dp"
+        android:layout_marginStart="24dp"
+        android:layout_marginEnd="34dp">
+
+        <TextView
+            android:id="@+id/dialog_content"
+            android:layout_width="128dp"
+            android:layout_height="wrap_content"
+            android:textSize="13sp"
+            android:textColor="#000000"
+            android:text="@string/filtershow_dialog_content"/>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="28dp"
+            android:layout_marginEnd="34dp">
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/original_photo"
+                android:layout_width="105dp"
+                android:layout_height="79dp"
+                android:layout_gravity="center"
+                android:src="@drawable/ref_city" />
+
+            <TextView
+                android:id="@+id/original"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:textColor="#000000"
+                android:textSize="9sp"
+                android:text="@string/filtershow_dialog_original_photo" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/filter_photo"
+                android:layout_width="105dp"
+                android:layout_height="79dp"
+                android:layout_gravity="center"
+                android:src="@drawable/ref_flowers" />
+
+            <TextView
+                android:id="@+id/filter"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:textColor="#000000"
+                android:textSize="9sp"
+                android:text="@string/filtershow_dialog_apply_photo"/>
+        </LinearLayout>
+        </LinearLayout>
+    </LinearLayout>
+
+    <CheckBox
+        android:id="@+id/filtershow_check_box"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="18dp"
+        android:layout_marginTop="20dp"
+        android:textSize="13sp"
+        android:text="@string/filtershow_dialog_checkbox" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="2px"
+        android:layout_marginTop="10dp"
+        android:background="#D8D8D8" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="260dp">
+
+        <Button
+            android:id="@+id/cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/cancel"
+            android:textSize="13dp"
+            style="?android:attr/buttonBarButtonStyle" />
+
+        <Button
+            android:id="@+id/ok"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/ok_continue"
+            android:textSize="13dp"
+            style="?android:attr/buttonBarButtonStyle" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout-land/filtershow_saturation_controls.xml b/res/layout-land/filtershow_saturation_controls.xml
index f452a64..6003b73 100644
--- a/res/layout-land/filtershow_saturation_controls.xml
+++ b/res/layout-land/filtershow_saturation_controls.xml
@@ -25,11 +25,11 @@
                     android:text="@string/editor_chan_sat_red"
                     android:textStyle="bold"
                     android:textColor="#ff8080"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/redValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/redSeekBar"
                     android:layout_width="match_parent"
@@ -42,11 +42,11 @@
                     android:text="@string/editor_chan_sat_yellow"
                     android:textStyle="bold"
                     android:textColor="#ffff80"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/yellowValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/yellowSeekBar"
                     android:layout_width="match_parent"
@@ -59,11 +59,11 @@
                     android:text="@string/editor_chan_sat_green"
                     android:textStyle="bold"
                     android:textColor="#80ff80"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/greenValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/greenSeekBar"
                     android:layout_width="match_parent"
@@ -76,11 +76,11 @@
                     android:text="@string/editor_chan_sat_cyan"
                     android:textStyle="bold"
                     android:textColor="#80ffff"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/cyanValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/cyanSeekBar"
                     android:layout_width="match_parent"
@@ -93,11 +93,11 @@
                     android:text="@string/editor_chan_sat_blue"
                     android:textStyle="bold"
                     android:textColor="#8080ff"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/blueValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/blueSeekBar"
                     android:layout_width="match_parent"
@@ -110,11 +110,11 @@
                     android:text="@string/editor_chan_sat_magenta"
                     android:textStyle="bold"
                     android:textColor="#ff80ff"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/magentaValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/magentaSeekBar"
                     android:layout_width="match_parent"
@@ -137,11 +137,11 @@
         <TextView
                 android:layout_gravity="left|center_vertical"
                 android:text="@string/editor_chan_sat_main"
-                android:layout_marginLeft="8dp"/>
+                android:layout_marginStart="8dp"/>
         <TextView
                 android:layout_gravity="right|center_vertical"
                 android:id="@+id/mainValue"
-                android:layout_marginRight="16dp"/>
+                android:layout_marginEnd="16dp"/>
         <SeekBar
                 android:id="@+id/mainSeekbar"
                 android:layout_width="match_parent"
diff --git a/res/layout-land/filtershow_vignette_controls.xml b/res/layout-land/filtershow_vignette_controls.xml
index 9bfb29f..7cb27e9 100644
--- a/res/layout-land/filtershow_vignette_controls.xml
+++ b/res/layout-land/filtershow_vignette_controls.xml
@@ -24,12 +24,12 @@
                     android:layout_gravity="left|center_vertical"
                     android:text="@string/vignette_exposure"
                     android:textStyle="bold"
-                    android:layout_marginLeft="8dp"
+                    android:layout_marginStart="8dp"
                     android:visibility="gone"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/exposureValue"
-                    android:layout_marginRight="16dp"
+                    android:layout_marginEnd="16dp"
                     android:visibility="gone"/>
             <SeekBar
                     android:id="@+id/exposureSeekBar"
@@ -43,11 +43,11 @@
                     android:layout_gravity="left|center_vertical"
                     android:text="@string/vignette_saturation"
                     android:textStyle="bold"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/saturationValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/saturationSeekBar"
                     android:layout_width="match_parent"
@@ -59,11 +59,11 @@
                     android:layout_gravity="left|center_vertical"
                     android:text="@string/vignette_contrast"
                     android:textStyle="bold"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/contrastValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/contrastSeekBar"
                     android:layout_width="match_parent"
@@ -75,11 +75,11 @@
                     android:layout_gravity="left|center_vertical"
                     android:text="@string/vignette_falloff"
                     android:textStyle="bold"
-                    android:layout_marginLeft="8dp"/>
+                    android:layout_marginStart="8dp"/>
             <TextView
                     android:layout_gravity="right|center_vertical"
                     android:id="@+id/falloffValue"
-                    android:layout_marginRight="16dp"/>
+                    android:layout_marginEnd="16dp"/>
             <SeekBar
                     android:id="@+id/falloffSeekBar"
                     android:layout_width="match_parent"
@@ -103,11 +103,11 @@
         <TextView
                 android:layout_gravity="left|center_vertical"
                 android:text="@string/vignette_main"
-                android:layout_marginLeft="8dp"/>
+                android:layout_marginStart="8dp"/>
         <TextView
                 android:layout_gravity="right|center_vertical"
                 android:id="@+id/mainVignetteValue"
-                android:layout_marginRight="16dp"/>
+                android:layout_marginEnd="16dp"/>
         <SeekBar
                 android:id="@+id/mainVignetteSeekbar"
                 android:layout_width="match_parent"
diff --git a/res/layout-land/keyguard_widget.xml b/res/layout-land/keyguard_widget.xml
index f0f4362..6839623 100644
--- a/res/layout-land/keyguard_widget.xml
+++ b/res/layout-land/keyguard_widget.xml
@@ -25,8 +25,8 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_centerVertical="true"
-        android:layout_alignParentRight="true"
-        android:layout_marginRight="@dimen/shutter_offset"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="@dimen/shutter_offset"
         android:contentDescription="@string/accessibility_shutter_button"
         android:scaleType="center"
         android:src="@drawable/btn_new_shutter" />
@@ -35,8 +35,8 @@
         android:layout_width="64dip"
         android:layout_height="64dip"
         android:layout_above="@id/shutter_button"
-        android:layout_alignParentRight="true"
-        android:layout_marginRight="6dip"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="6dip"
         android:layout_marginTop="-5dip"
         layout="@layout/menu_indicators_keyguard" />
 
@@ -44,8 +44,8 @@
         android:id="@+id/camera_switcher"
         style="@style/SwitcherButton"
         android:layout_below="@id/shutter_button"
-        android:layout_alignParentRight="true"
-        android:layout_marginRight="2dip"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="2dip"
         android:contentDescription="@string/accessibility_mode_picker"
         android:scaleType="center"
         android:src="@drawable/ic_switch_camera" />
@@ -54,8 +54,8 @@
         android:id="@+id/camera_switcher_ind"
         style="@style/SwitcherButton"
         android:layout_below="@id/shutter_button"
-        android:layout_alignParentRight="true"
-        android:layout_marginRight="2dip"
+        android:layout_alignParentEnd="true"
+        android:layout_marginEnd="2dip"
         android:contentDescription="@string/accessibility_mode_picker"
         android:scaleType="center"
         android:src="@drawable/ic_switcher_menu_indicator" />
diff --git a/res/layout-land/on_screen_hint.xml b/res/layout-land/on_screen_hint.xml
index 59b0d1a..7406d0a 100644
--- a/res/layout-land/on_screen_hint.xml
+++ b/res/layout-land/on_screen_hint.xml
@@ -23,7 +23,7 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:textAppearance="@style/OnScreenHintTextAppearance.Small"
-            android:textColor="#ffffffff"
+            android:textColor="@color/white"
             android:shadowColor="#BB000000"
             android:shadowRadius="2.75" />
 </LinearLayout>
diff --git a/res/layout-land/review_module_control.xml b/res/layout-land/review_module_control.xml
index 9f8b0cd..6e0ee4a 100644
--- a/res/layout-land/review_module_control.xml
+++ b/res/layout-land/review_module_control.xml
@@ -16,21 +16,21 @@
 <com.android.camera.ui.RotatableLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
         style="@style/CameraControls"
-        android:layout_gravity="right|center_vertical"
-        android:layout_marginRight="2dip">
+        android:layout_gravity="end|center_vertical"
+        android:layout_marginEnd="2dip">
     <ImageView android:id="@+id/btn_done"
             style="@style/ReviewControlIcon"
             android:contentDescription="@string/accessibility_review_ok"
             android:visibility="gone"
             android:scaleType="center"
-            android:layout_gravity="top|right"
+            android:layout_gravity="top|end"
             android:background="@drawable/bg_pressed"
             android:src="@drawable/ic_menu_done_holo_light" />
 
     <ImageView android:id="@+id/btn_retake"
         style="@style/ReviewControlIcon"
         android:contentDescription="@string/accessibility_review_retake"
-        android:layout_gravity="right|center_vertical"
+        android:layout_gravity="end|center_vertical"
         android:scaleType="center"
         android:focusable="true"
         android:visibility="gone"
@@ -42,7 +42,7 @@
             android:contentDescription="@string/accessibility_review_cancel"
             android:visibility="gone"
             android:scaleType="center"
-            android:layout_gravity="bottom|right"
+            android:layout_gravity="bottom|end"
             android:background="@drawable/bg_pressed"
             android:src="@drawable/ic_menu_cancel_holo_light" />
 </com.android.camera.ui.RotatableLayout>
diff --git a/res/layout-land/switcher_popup.xml b/res/layout-land/switcher_popup.xml
index fc2d7bc..ebb4243 100644
--- a/res/layout-land/switcher_popup.xml
+++ b/res/layout-land/switcher_popup.xml
@@ -19,10 +19,10 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="bottom|right"
-    android:layout_marginRight="8dip"
+    android:layout_marginEnd="8dip"
     android:layout_marginBottom="8dip"
-    android:paddingLeft="8dip"
-    android:paddingRight="8dip"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
     android:paddingTop="16dip"
     android:paddingBottom="16dip"
     android:background="#80000000" />
diff --git a/res/layout-port/camera_controls.xml b/res/layout-port/camera_controls.xml
index 5f89830..e3ad8c1 100644
--- a/res/layout-port/camera_controls.xml
+++ b/res/layout-port/camera_controls.xml
@@ -31,7 +31,7 @@
             android:layout_height="64dip"
             android:layout_gravity="bottom|right"
             android:layout_marginBottom="6dip"
-            android:layout_marginRight="-5dip" />
+            android:layout_marginEnd="-5dip" />
 
         <com.android.camera.ui.PieMenuButton
             android:id="@+id/menu"
diff --git a/res/layout-port/keyguard_widget.xml b/res/layout-port/keyguard_widget.xml
index 28b59c4..40a601f 100644
--- a/res/layout-port/keyguard_widget.xml
+++ b/res/layout-port/keyguard_widget.xml
@@ -32,15 +32,15 @@
     <include layout="@layout/menu_indicators_keyguard"
         android:layout_width="64dip"
         android:layout_height="64dip"
-        android:layout_toRightOf="@id/shutter"
+        android:layout_toEndOf="@id/shutter"
         android:layout_alignParentBottom="true"
         android:layout_marginBottom="6dip"
-        android:layout_marginRight="-5dip" />
+        android:layout_marginEnd="-5dip" />
 
     <ImageView
         android:id="@+id/camera_switcher"
         style="@style/SwitcherButton"
-        android:layout_toLeftOf="@id/shutter"
+        android:layout_toStartOf="@id/shutter"
         android:layout_alignParentBottom="true"
         android:layout_marginBottom="2dip"
         android:scaleType="center"
@@ -50,7 +50,7 @@
     <ImageView
         android:id="@+id/camera_switcher_ind"
         style="@style/SwitcherButton"
-        android:layout_toLeftOf="@id/shutter"
+        android:layout_toStartOf="@id/shutter"
         android:layout_alignParentBottom="true"
         android:layout_marginBottom="2dip"
         android:scaleType="center"
diff --git a/res/layout-port/on_screen_hint.xml b/res/layout-port/on_screen_hint.xml
index 467b67f..7a24f7d 100644
--- a/res/layout-port/on_screen_hint.xml
+++ b/res/layout-port/on_screen_hint.xml
@@ -23,7 +23,7 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:textAppearance="@style/OnScreenHintTextAppearance.Small"
-            android:textColor="#ffffffff"
+            android:textColor="@color/white"
             android:shadowColor="#BB000000"
             android:shadowRadius="2.75" />
 </LinearLayout>
diff --git a/res/layout-port/review_module_control.xml b/res/layout-port/review_module_control.xml
index 3c4280e..c7b04f7 100644
--- a/res/layout-port/review_module_control.xml
+++ b/res/layout-port/review_module_control.xml
@@ -23,7 +23,7 @@
             android:contentDescription="@string/accessibility_review_ok"
             android:visibility="gone"
             android:scaleType="center"
-            android:layout_gravity="right|bottom"
+            android:layout_gravity="end|bottom"
             android:background="@drawable/bg_pressed"
             android:src="@drawable/ic_menu_done_holo_light" />
 
@@ -42,7 +42,7 @@
             android:contentDescription="@string/accessibility_review_cancel"
             android:visibility="gone"
             android:scaleType="center"
-            android:layout_gravity="left|bottom"
+            android:layout_gravity="start|bottom"
             android:background="@drawable/bg_pressed"
             android:src="@drawable/ic_menu_cancel_holo_light" />
 </com.android.camera.ui.RotatableLayout>
diff --git a/res/layout-port/switcher_popup.xml b/res/layout-port/switcher_popup.xml
index 8fe09a3..609f869 100644
--- a/res/layout-port/switcher_popup.xml
+++ b/res/layout-port/switcher_popup.xml
@@ -19,10 +19,10 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="bottom|left"
-    android:layout_marginLeft="8dip"
+    android:layout_marginStart="8dip"
     android:layout_marginBottom="8dip"
-    android:paddingLeft="16dip"
-    android:paddingRight="16dip"
+    android:paddingStart="16dip"
+    android:paddingEnd="16dip"
     android:paddingTop="8dip"
     android:paddingBottom="8dip"
     android:background="#80000000" />
diff --git a/res/layout/action_bar_text.xml b/res/layout/action_bar_text.xml
index a332647..10839ea 100644
--- a/res/layout/action_bar_text.xml
+++ b/res/layout/action_bar_text.xml
@@ -21,8 +21,8 @@
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceMedium"
     android:gravity="center_vertical"
-    android:paddingLeft="18dp"
-    android:paddingRight="18dp"
+    android:paddingStart="18dp"
+    android:paddingEnd="18dp"
     android:singleLine="true"
     android:minHeight="?attr/listPreferredItemHeightSmall"
 />
diff --git a/res/layout/action_bar_two_line_text.xml b/res/layout/action_bar_two_line_text.xml
index 92a4af9..6233d8e 100644
--- a/res/layout/action_bar_two_line_text.xml
+++ b/res/layout/action_bar_two_line_text.xml
@@ -19,7 +19,7 @@
         android:orientation="vertical"
         android:gravity="center_vertical"
         android:duplicateParentState="false"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:layout_width="wrap_content" >
         <TextView
             android:id="@android:id/text1"
@@ -35,7 +35,7 @@
             android:singleLine="true"
             android:ellipsize="end"
             android:includeFontPadding="false"
-            android:layout_marginRight="4dp"
+            android:layout_marginEnd="4dp"
             android:layout_below="@android:id/text1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />
diff --git a/res/layout/action_mode.xml b/res/layout/action_mode.xml
index 6c516e6..186ce5b 100644
--- a/res/layout/action_mode.xml
+++ b/res/layout/action_mode.xml
@@ -24,25 +24,22 @@
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="wrap_content"
             android:layout_height="match_parent">
-        <ImageView android:layout_gravity="right"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
+
+        <ImageView android:layout_gravity="right|center_vertical"
+                android:layout_width="8dp"
+                android:layout_height="8dp"
                 android:src="@drawable/dropdown_ic_arrow_normal_holo_dark" />
         <Button android:id="@+id/selection_menu"
                 style="?android:attr/actionButtonStyle"
                 android:divider="?android:attr/listDividerAlertDialog"
                 android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
-                android:textColor="?android:attr/actionMenuTextColor"
+                android:textColor="@color/black_transparent_4"
+                android:textSize="18sp"
                 android:singleLine="true"
-                android:gravity="left|center_vertical"
-                android:paddingRight="25dip"
+                android:gravity="start|center_vertical"
+                android:paddingEnd="15dip"
+                android:paddingStart="0dp"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent" />
     </FrameLayout>
-    <ImageView android:layout_marginLeft="16dip"
-            android:layout_marginRight="8dip"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:gravity="bottom"
-            android:src="@drawable/cab_divider_vertical_dark" />
 </LinearLayout>
diff --git a/res/layout/activity_three_dimensional.xml b/res/layout/activity_three_dimensional.xml
new file mode 100644
index 0000000..7244273
--- /dev/null
+++ b/res/layout/activity_three_dimensional.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>

+<!--

+  Copyright (c) 2016, The Linux Foundation. All rights reserved.

+

+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED

+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF

+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT

+  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.

+-->

+<merge 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"

+    android:orientation="vertical"

+    tools:context="com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity">

+

+    <com.android.gallery3d.app.dualcam3d.GLView

+        android:id="@+id/image"

+        android:layout_width="match_parent"

+        android:layout_height="match_parent" />

+

+    <LinearLayout

+        android:id="@+id/mode_3d"

+        android:layout_width="wrap_content"

+        android:layout_height="wrap_content"

+        android:layout_gravity="top|end"

+        android:paddingTop="130dp"

+        android:paddingRight="50dp"

+        android:orientation="vertical">

+

+        <ImageButton

+            android:id="@+id/three_dimensional"

+            android:layout_width="wrap_content"

+            android:layout_height="wrap_content"

+            android:layout_gravity="center"

+            android:background="?android:attr/actionBarItemBackground"

+            android:src="@drawable/three_d"/>

+

+        <ImageButton

+            android:id="@+id/mode_gyro"

+            android:layout_width="wrap_content"

+            android:layout_height="40dp"

+            android:text="@string/grad"

+            android:textAlignment="center"

+            android:visibility="gone" />

+

+        <ImageButton

+            android:id="@+id/mode_auto"

+            android:layout_width="wrap_content"

+            android:layout_height="40dp"

+            android:text="@string/auto"

+            android:textAlignment="center"

+            android:visibility="gone" />

+

+        <ImageButton

+            android:id="@+id/mode_touch"

+            android:layout_width="wrap_content"

+            android:layout_height="40dp"

+            android:text="@string/trueportrait_touch_up"

+            android:textAlignment="center"

+            android:visibility="gone" />

+    </LinearLayout>

+

+</merge>

diff --git a/res/layout/album_header.xml b/res/layout/album_header.xml
index 76c9a45..caae962 100644
--- a/res/layout/album_header.xml
+++ b/res/layout/album_header.xml
@@ -27,8 +27,8 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:paddingLeft="15dip"
+        android:layout_alignParentStart="true"
+        android:paddingStart="15dip"
         android:paddingBottom="10dip"
         android:paddingTop="20dip"
         android:background="@drawable/white_text_bg_gradient"
diff --git a/res/layout/appwidget_drm_empty_item.xml b/res/layout/appwidget_drm_empty_item.xml
new file mode 100644
index 0000000..8261dbe
--- /dev/null
+++ b/res/layout/appwidget_drm_empty_item.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+ 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:background="@drawable/appwidget_photo_border" >
+
+    <RelativeLayout
+        android:layout_width="@dimen/stack_photo_width"
+        android:layout_height="@dimen/stack_photo_height"
+        android:background="@android:color/darker_gray" >
+
+        <ImageView
+            android:id="@+id/drm_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:background="@drawable/drm_image" />
+    </RelativeLayout>
+s
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/appwidget_main.xml b/res/layout/appwidget_main.xml
index 0accabb..368d90b 100644
--- a/res/layout/appwidget_main.xml
+++ b/res/layout/appwidget_main.xml
@@ -31,6 +31,7 @@
                     android:layout_width="@dimen/stack_photo_width"
                     android:layout_height="@dimen/stack_photo_height"
                     android:gravity="center"
+                    android:textColor="@android:color/black"
                     android:text="@string/appwidget_empty_text"/>
         </FrameLayout>
     </RelativeLayout>
diff --git a/res/layout/appwidget_photo_item.xml b/res/layout/appwidget_photo_item.xml
index a56a6d7..25e88f5 100644
--- a/res/layout/appwidget_photo_item.xml
+++ b/res/layout/appwidget_photo_item.xml
@@ -24,4 +24,12 @@
             android:layout_width="wrap_content"
             android:scaleType="fitCenter"
             android:adjustViewBounds="true" />
+
+    <ImageView
+        android:id="@+id/drm_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:background="@drawable/drm_image" />
+
 </FrameLayout>
diff --git a/res/layout/bookmark.xml b/res/layout/bookmark.xml
new file mode 100644
index 0000000..ac4ac34
--- /dev/null
+++ b/res/layout/bookmark.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <TextView
+        android:id="@android:id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_centerInParent="true"
+        android:gravity="center"
+        android:paddingBottom="30dip"
+        android:text="@string/bookmark_empty"
+        android:textAppearance="?android:attr/textAppearanceLarge"
+        android:visibility="gone" />
+</FrameLayout>
diff --git a/res/layout/bookmark_edit_dialog.xml b/res/layout/bookmark_edit_dialog.xml
new file mode 100644
index 0000000..8282d39
--- /dev/null
+++ b/res/layout/bookmark_edit_dialog.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="8dip" >
+
+        <TextView
+            style="?android:attr/textAppearanceSmallInverse"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/bookmark_title" />
+
+        <EditText
+            android:id="@+id/title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2dip"
+            android:inputType="text"
+            android:scrollHorizontally="true"
+            android:singleLine="true" />
+
+        <TextView
+            style="?android:attr/textAppearanceSmallInverse"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/bookmark_location" />
+
+        <EditText
+            android:id="@+id/data"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2dip"
+            android:inputType="textUri"
+            android:scrollHorizontally="true"
+            android:singleLine="true" />
+    </LinearLayout>
+
+</ScrollView>
diff --git a/res/layout/bookmark_item.xml b/res/layout/bookmark_item.xml
new file mode 100644
index 0000000..3fb2fab
--- /dev/null
+++ b/res/layout/bookmark_item.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/panel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="6dip" >
+
+    <TextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <TextView
+        android:id="@+id/data"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/res/layout/camera_filmstrip.xml b/res/layout/camera_filmstrip.xml
index d94a9d2..7230add 100644
--- a/res/layout/camera_filmstrip.xml
+++ b/res/layout/camera_filmstrip.xml
@@ -32,8 +32,8 @@
         android:background="@drawable/transparent_button_background"
         android:clickable="true"
         android:paddingBottom="5dp"
-        android:paddingLeft="5dp"
-        android:paddingRight="5dp"
+        android:paddingStart="5dp"
+        android:paddingEnd="5dp"
         android:paddingTop="5dp"
         android:visibility="gone"
         android:src="@drawable/ic_view_photosphere" />
@@ -44,8 +44,8 @@
         android:layout_height="wrap_content"
         android:layout_gravity="bottom|center_horizontal"
         android:paddingBottom="52dp"
-        android:paddingLeft="5dp"
-        android:paddingRight="5dp"
+        android:paddingStart="5dp"
+        android:paddingEnd="5dp"
         android:paddingTop="5dp"
         android:visibility="gone"
         android:orientation="vertical">
@@ -53,18 +53,18 @@
         <TextView
             android:id="@+id/pano_stitching_progress_text"
             android:text="@string/pano_progress_text"
-            android:textColor="#ffffffff"
+            android:textColor="@color/white"
             android:textSize="14dp"
-            android:shadowColor="#ff000000"
+            android:shadowColor="@color/black"
             android:shadowDx="0"
             android:shadowDy="0"
             android:shadowRadius="2"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
             android:paddingBottom="8dp"
             android:visibility="visible"
-            android:layout_gravity="right"/>
+            android:layout_gravity="end"/>
 
         <ProgressBar
             android:id="@+id/pano_stitching_progress_bar"
diff --git a/res/layout/choose_widget_type.xml b/res/layout/choose_widget_type.xml
index 5f1739a..d8af048 100644
--- a/res/layout/choose_widget_type.xml
+++ b/res/layout/choose_widget_type.xml
@@ -16,8 +16,8 @@
 
 <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/widget_type"
-        android:paddingLeft="32dp"
-        android:paddingRight="32dp"
+        android:paddingStart="32dp"
+        android:paddingEnd="32dp"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">
@@ -42,8 +42,8 @@
     <View android:layout_width="match_parent"
             android:layout_height="1dp"
             android:layout_weight="0"
-            android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
+            android:layout_marginStart="16dp"
+            android:layout_marginEnd="16dp"
             android:background="?android:attr/dividerHorizontal" />
     <Button style="?android:attr/buttonBarButtonStyle"
             android:id="@+id/cancel"
diff --git a/res/layout/count_down_to_capture.xml b/res/layout/count_down_to_capture.xml
index 68276ad..5cf1e3f 100644
--- a/res/layout/count_down_to_capture.xml
+++ b/res/layout/count_down_to_capture.xml
@@ -27,7 +27,7 @@
     <TextView android:id="@+id/count_down_title"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:paddingLeft="10dp"
+        android:paddingStart="10dp"
         android:paddingTop="20dp"
         android:textSize="20sp"
         android:textColor="@android:color/white"
diff --git a/res/layout/countdown_setting_popup.xml b/res/layout/countdown_setting_popup.xml
index 22acd92..1a314ad 100644
--- a/res/layout/countdown_setting_popup.xml
+++ b/res/layout/countdown_setting_popup.xml
@@ -55,8 +55,8 @@
                 android:layout_width="160dp"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
-                android:layout_marginLeft="16dip"
-                android:layout_marginRight="16dip"
+                android:layout_marginStart="16dip"
+                android:layout_marginEnd="16dip"
                 android:focusable="false" />
         </LinearLayout>
 
diff --git a/res/layout/details.xml b/res/layout/details.xml
index 1fea0a0..0c3622b 100644
--- a/res/layout/details.xml
+++ b/res/layout/details.xml
@@ -18,6 +18,7 @@
     android:id="@android:id/text1"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:textSize="16sp"
+    android:textColor="@color/albumset_label_background"
     android:gravity="start"
 />
diff --git a/res/layout/details_list.xml b/res/layout/details_list.xml
index b80ab6c..aa5842c 100644
--- a/res/layout/details_list.xml
+++ b/res/layout/details_list.xml
@@ -17,6 +17,9 @@
 <ListView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="16dp"
+    android:paddingTop="20dp"
+    android:paddingBottom="16dp"
+    android:paddingLeft="24dp"
+    android:paddingRight="24dp"
     android:dividerHeight="8dp"
 />
diff --git a/res/layout/dialog_picker.xml b/res/layout/dialog_picker.xml
index ccc5121..fc5f287 100644
--- a/res/layout/dialog_picker.xml
+++ b/res/layout/dialog_picker.xml
@@ -26,8 +26,8 @@
     </FrameLayout>
     <ImageView android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
+            android:layout_marginStart="16dp"
+            android:layout_marginEnd="16dp"
             android:background="@drawable/list_divider_holo_dark" />
     <Button style="?android:attr/buttonBarButtonStyle"
             android:id="@+id/cancel"
diff --git a/res/layout/do_not_show_again_dialog.xml b/res/layout/do_not_show_again_dialog.xml
new file mode 100644
index 0000000..a9bbb43
--- /dev/null
+++ b/res/layout/do_not_show_again_dialog.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="8dip"
+    android:paddingBottom="8dip"
+    android:paddingEnd="?android:attr/dialogPreferredPadding"
+    android:paddingStart="?android:attr/dialogPreferredPadding"
+    android:orientation="vertical" >
+
+    <ScrollView
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_weight="2">
+        <TextView
+            android:id="@+id/message"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            style="@android:style/TextAppearance.Material.Subhead" />
+    </ScrollView>
+
+    <CheckBox
+        android:id="@+id/do_not_show_chk"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:gravity="center"
+        android:layout_weight="1"
+        android:minHeight="20dp"
+        android:paddingEnd="6dp"
+        style="@android:style/TextAppearance.Material.Subhead"
+        android:text="@string/do_not_show_again" />
+
+</LinearLayout>
diff --git a/res/layout/drawer_list_item.xml b/res/layout/drawer_list_item.xml
new file mode 100644
index 0000000..bee7656
--- /dev/null
+++ b/res/layout/drawer_list_item.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="48dp"
+    android:paddingTop="10dp"
+    android:paddingBottom="10dp">
+
+    <ImageView
+        android:id="@+id/ivItem"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentStart="true"
+        android:layout_marginStart="16dp"
+        />
+
+    <TextView
+        android:id="@+id/itemTitle"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textSize="12sp"
+        android:layout_centerVertical="true"
+        android:fontFamily="sans-serif-medium"
+        android:textColor="@color/black"
+        android:alpha="0.87"
+        android:layout_marginStart="64dp"
+       />
+</RelativeLayout>
diff --git a/res/layout/editor_grad_button.xml b/res/layout/editor_grad_button.xml
index 4d1b10b..032eb68 100644
--- a/res/layout/editor_grad_button.xml
+++ b/res/layout/editor_grad_button.xml
@@ -20,7 +20,7 @@
     android:layout_height="wrap_content"
     android:layout_weight="1"
     android:layout_alignParentTop="true"
-    android:layout_marginLeft="26dp"
+    android:layout_marginStart="26dp"
     android:layout_marginTop="21dp"
     android:orientation="horizontal" >
 
diff --git a/res/layout/filtershow_actionbar.xml b/res/layout/filtershow_actionbar.xml
index 5f0aa3f..a71e933 100644
--- a/res/layout/filtershow_actionbar.xml
+++ b/res/layout/filtershow_actionbar.xml
@@ -14,14 +14,32 @@
      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="match_parent"
-    android:background="@drawable/filtershow_button_background"
-    android:id="@+id/filtershow_done"
-    android:textAllCaps="true"
-    android:text="@string/save"
-    android:gravity="center_vertical"
-    android:textSize="14sp"
-    android:drawableLeft="@drawable/menu_save_photo"
-    android:drawablePadding="8dip" />
\ No newline at end of file
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@android:style/Theme.DeviceDefault"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/toolbar_height"
+    android:orientation="horizontal">
+
+    <ImageButton
+        android:id="@+id/filtershow_exit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="?android:attr/actionBarItemBackground"
+        android:scaleType="fitCenter"
+        android:src="@drawable/cancel"
+        android:layout_gravity="left|center_vertical"
+        android:layout_marginStart="@dimen/toolbar_exit_padding_left" />
+
+    <TextView
+        android:id="@+id/filtershow_done"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:layout_marginEnd="13dp"
+        android:textSize="17sp"
+        android:text="@string/save"
+        android:textAllCaps="true"
+        android:layout_gravity="center_vertical|right"
+        android:textColor="@color/white" />
+
+</FrameLayout>
diff --git a/res/layout/filtershow_actionbar_dualcam_fusion.xml b/res/layout/filtershow_actionbar_dualcam_fusion.xml
new file mode 100644
index 0000000..c5cec25
--- /dev/null
+++ b/res/layout/filtershow_actionbar_dualcam_fusion.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1">
+
+    <ImageButton
+        android:id="@+id/pick_underlay"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentRight="true"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_bg_select" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar_effects.xml b/res/layout/filtershow_actionbar_effects.xml
new file mode 100644
index 0000000..48ed3b3
--- /dev/null
+++ b/res/layout/filtershow_actionbar_effects.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="48dip"
+    android:baselineAligned="false"
+    android:orientation="horizontal"
+    android:visibility="visible" >
+
+    <ImageButton
+        android:id="@+id/cancelFilter"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:layout_gravity="left|center_vertical"
+        android:layout_weight=".1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:gravity="center"
+        android:src="@drawable/cancel"
+        android:paddingStart="16dp"
+        android:textSize="18dip" />
+
+    <LinearLayout
+        android:id="@+id/panelAccessoryViewList"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:gravity="center"
+        android:orientation="horizontal"
+        android:visibility="visible" >
+
+        <com.android.gallery3d.filtershow.editors.SwapButton
+            android:id="@+id/applyEffect"
+            android:layout_width="@dimen/swap_button_width"
+            android:layout_height="@dimen/swap_button_height"
+            android:layout_gravity="center_vertical|center_horizontal"
+            android:background="@android:color/transparent"
+            android:drawableEnd="@drawable/spinner_triangle"
+            android:gravity="center"
+            android:text="@string/apply_effect"
+            android:textColor="@color/white"
+            android:textSize="16sp" />
+    </LinearLayout>
+
+    <ImageButton
+        android:id="@+id/applyFilter"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:layout_gravity="right|center_vertical"
+        android:layout_weight=".1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:gravity="center"
+        android:src="@drawable/done"
+        android:paddingEnd="16dp"
+        android:textSize="18dip" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar_new.xml b/res/layout/filtershow_actionbar_new.xml
new file mode 100644
index 0000000..1e56b8d
--- /dev/null
+++ b/res/layout/filtershow_actionbar_new.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="@dimen/toolbar_height"
+    android:paddingTop="15dp">
+
+    <ImageButton
+        android:id="@+id/imgCancel"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentLeft="true"
+        android:background="@android:color/transparent"
+        android:src="@drawable/cancel"
+        android:paddingLeft="16dp"/>
+
+    <ImageButton
+        android:id="@+id/imgDone"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:background="@android:color/transparent"
+        android:src="@drawable/done"
+        android:paddingRight="16dp" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar_trueportrait.xml b/res/layout/filtershow_actionbar_trueportrait.xml
new file mode 100644
index 0000000..11e81a8
--- /dev/null
+++ b/res/layout/filtershow_actionbar_trueportrait.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1" >
+
+    <ImageButton
+        android:id="@+id/editMask"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentRight="true"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_touch_up" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar_trueportrait_fusion.xml b/res/layout/filtershow_actionbar_trueportrait_fusion.xml
new file mode 100644
index 0000000..44e151b
--- /dev/null
+++ b/res/layout/filtershow_actionbar_trueportrait_fusion.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1" >
+
+    <ImageButton
+        android:id="@+id/pick_underlay"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentRight="true"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_bg_select" />
+
+    <ImageButton
+        android:id="@+id/editMask"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_toLeftOf="@id/pick_underlay"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_touch_up" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_actionbar_trueportrait_mask.xml b/res/layout/filtershow_actionbar_trueportrait_mask.xml
new file mode 100644
index 0000000..f992e76
--- /dev/null
+++ b/res/layout/filtershow_actionbar_trueportrait_mask.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_weight="1" >
+
+    <ImageButton
+        android:id="@+id/maskUndo"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentLeft="true"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_undo" />
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_centerInParent="true" >
+
+        <ToggleButton
+            android:id="@+id/maskForeground"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:background="@drawable/tp_mask_toggle"
+            android:textColor="@color/primary_text"
+            android:paddingEnd="16dp"
+            android:paddingStart="16dp"
+            android:textOff="@string/foreground"
+            android:textOn="@string/foreground" />
+
+        <Space
+	        android:layout_width="5dp"
+	        android:layout_height="0dp"/>
+
+        <ToggleButton
+            android:id="@+id/maskBackground"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:background="@drawable/tp_mask_toggle"
+            android:textColor="@color/primary_text"
+            android:paddingEnd="16dp"
+            android:paddingStart="16dp"
+            android:textOff="@string/background"
+            android:textOn="@string/background" />
+    </LinearLayout>
+
+    <ImageButton
+        android:id="@+id/maskHelp"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentRight="true"
+        android:background="@android:color/transparent"
+        android:paddingEnd="16dp"
+        android:paddingStart="16dp"
+        android:src="@drawable/tp_help" />
+
+</RelativeLayout>
diff --git a/res/layout/filtershow_activity.xml b/res/layout/filtershow_activity.xml
index 79c315b..741b3db 100644
--- a/res/layout/filtershow_activity.xml
+++ b/res/layout/filtershow_activity.xml
@@ -16,85 +16,73 @@
 -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-             android:layout_width="match_parent"
-             android:layout_height="match_parent"
-             android:id="@+id/mainView"
-             android:background="@drawable/filtershow_tiled_background">
-
-    <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:orientation="vertical">
+    android:id="@+id/mainView"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/background_screen" >
 
         <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_marginTop="?android:attr/actionBarSize" >
+
+            <RelativeLayout
+                android:id="@+id/imageContainer"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_weight="1">
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:orientation="horizontal" >
 
-            <ProgressBar
-                    android:id="@+id/loading"
-                    style="@android:style/Widget.Holo.ProgressBar.Large"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:indeterminate="true"
-                    android:indeterminateOnly="true"
-                    android:background="@null"/>
-
-            <LinearLayout
-                    android:layout_weight="1"
+                <FrameLayout
+                    android:id="@+id/editorContainer"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:orientation="horizontal">
-
-                <FrameLayout
-                        android:id="@+id/central_panel_container"
-                        android:layout_gravity="center"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:visibility="gone"/>
-
-                <FrameLayout
-                        android:id="@+id/editorContainer"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"/>
+                    android:layout_weight="1"
+                    android:visibility="gone" />
 
                 <com.android.gallery3d.filtershow.imageshow.ImageShow
-                        android:id="@+id/imageShow"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_weight="1"/>
+                    android:id="@+id/imageShow"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:layout_weight="1" />
 
+                <ImageButton
+                    android:id="@+id/imgComparison"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentRight="true"
+                    android:layout_marginRight="@dimen/compare_margin_right"
+                    android:layout_marginTop="@dimen/compare_margin_top"
+                    android:background="@android:color/transparent"
+                    android:src="@drawable/comparison"
+                    android:visibility="visible" />
+            </RelativeLayout>
 
-            </LinearLayout>
-
-        </FrameLayout>
-
-        <com.android.gallery3d.filtershow.CenteredLinearLayout
-                xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
+            <com.android.gallery3d.filtershow.CenteredLinearLayout
+                xmlns:custom="http://schemas.android.com/apk/res/org.codeaurora.gallery"
                 android:id="@+id/mainPanel"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center|bottom"
-                custom:max_width="650dip"
-                android:orientation="vertical" >
+                android:background="@android:color/transparent"
+                android:orientation="vertical"
+                custom:max_width="650dip" >
 
-            <FrameLayout android:id="@+id/main_panel_container"
-                         android:layout_gravity="center"
-                         android:layout_width="match_parent"
-                         android:layout_height="0dip"
-                         android:layout_weight="1" />
-
-        </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-    </LinearLayout>
+                <FrameLayout
+                    android:id="@+id/main_panel_container"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dip"
+                    android:background="@android:color/transparent"
+                    android:layout_gravity="center"
+                    android:layout_weight="1" />
+            </com.android.gallery3d.filtershow.CenteredLinearLayout>
+        </FrameLayout>
 
     <com.android.gallery3d.filtershow.category.CategorySelected
-            android:layout_width="@dimen/category_panel_icon_size"
-            android:layout_height="@dimen/category_panel_icon_size"
-            android:id="@+id/categorySelectedIndicator"
-            android:visibility="invisible"/>
+        android:id="@+id/categorySelectedIndicator"
+        android:layout_width="@dimen/category_panel_icon_size"
+        android:layout_height="@dimen/category_panel_icon_size"
+        android:visibility="gone" />
 
 </FrameLayout>
diff --git a/res/layout/filtershow_bottom_panel.xml b/res/layout/filtershow_bottom_panel.xml
new file mode 100644
index 0000000..7d029d5
--- /dev/null
+++ b/res/layout/filtershow_bottom_panel.xml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<com.android.gallery3d.filtershow.CenteredLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@android:style/Theme.DeviceDefault"
+    android:id="@+id/bottom_panel"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center|bottom"
+    android:background="@color/bottom_panel_background_color"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:id="@+id/effectsContainer"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@android:color/transparent">
+
+        <ImageButton
+            android:id="@+id/fxButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:scaleType="centerInside"
+            android:src="@drawable/color_background" />
+
+        <ImageButton
+            android:id="@+id/borderButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/frames_background" />
+
+        <ImageButton
+            android:id="@+id/geometryButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/crop_background" />
+
+        <ImageButton
+            android:id="@+id/colorsButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/exposure_background" />
+
+        <ImageButton
+            android:id="@+id/makeupButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/beautify_background"
+            android:visibility="gone" />
+
+        <ImageButton
+            android:id="@+id/dualCamButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/dualcamera_background"
+            android:visibility="gone" />
+
+        <ImageButton
+            android:id="@+id/trueScannerButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/truescanner_background" />
+
+        <ImageButton
+            android:id="@+id/hazeBusterButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/hazebuster" />
+
+        <ImageButton
+            android:id="@+id/seeStraightButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="?android:attr/actionBarItemBackground"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/seestraight" />
+
+        <ImageButton
+            android:id="@+id/truePortraitButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@android:color/transparent"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/trueportrait_background" />
+
+        <ImageButton
+            android:id="@+id/waterMarkButton"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@android:color/transparent"
+            android:padding="2dip"
+            android:scaleType="centerInside"
+            android:src="@drawable/watermark" />
+    </LinearLayout>
+</com.android.gallery3d.filtershow.CenteredLinearLayout>
diff --git a/res/layout/filtershow_category_geometry_panel.xml b/res/layout/filtershow_category_geometry_panel.xml
new file mode 100644
index 0000000..50515d6
--- /dev/null
+++ b/res/layout/filtershow_category_geometry_panel.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@android:style/Theme.DeviceDefault"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/transparent"
+    android:orientation="vertical">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/category_panel_height"
+        android:background="@android:color/transparent"
+        android:clickable="true"
+        android:orientation="horizontal">
+
+        <LinearLayout
+            android:id="@+id/leftPanel"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:background="@android:color/transparent"
+            android:orientation="vertical" >
+
+            <ImageButton
+                android:id="@+id/leftButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size"
+                android:scaleType="centerInside"
+                android:background="?android:attr/actionBarItemBackground"
+                android:layout_marginTop="@dimen/crop_icon_margin_padding" />
+
+            <TextView
+                android:id="@+id/leftText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/centerPanel"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:background="@android:color/transparent"
+            android:orientation="vertical">
+
+            <ImageButton
+                android:id="@+id/centerButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size"
+                android:scaleType="centerInside"
+                android:background="?android:attr/actionBarItemBackground"
+                android:layout_marginTop="@dimen/crop_icon_margin_padding" />
+
+            <TextView
+                android:id="@+id/centerText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/rightPanel"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:background="@android:color/transparent"
+            android:orientation="vertical">
+
+            <ImageButton
+                android:id="@+id/rightButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size"
+                android:scaleType="centerInside"
+                android:layout_marginTop="@dimen/crop_icon_margin_padding"
+                android:background="?android:attr/actionBarItemBackground" />
+
+            <TextView
+                android:id="@+id/rightText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/bottom_panel"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/category_actionbar_panel_height"
+        android:background="@color/edit_actionbar_background"
+        android:visibility="gone">
+
+        <ImageButton
+            android:id="@+id/cancel"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="?android:attr/actionBarItemBackground"
+            android:src="@drawable/cancel" />
+
+        <TextView
+            android:id="@+id/editor_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="16sp"
+            android:textColor="#fff"
+            android:layout_gravity="center"/>
+
+        <ImageButton
+            android:id="@+id/done"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="?android:attr/actionBarItemBackground"
+            android:layout_gravity="right"
+            android:src="@drawable/done" />
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/filtershow_category_panel.xml b/res/layout/filtershow_category_panel.xml
index c1b8bbe..74ead63 100644
--- a/res/layout/filtershow_category_panel.xml
+++ b/res/layout/filtershow_category_panel.xml
@@ -17,8 +17,8 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="48dip"
-    android:background="@color/background_main_toolbar" >
+    android:layout_height="80dp"
+    android:background="@color/edit_actionbar_background" >
 
     <ImageButton
         android:id="@+id/fxButton"
diff --git a/res/layout/filtershow_category_panel_new.xml b/res/layout/filtershow_category_panel_new.xml
index 8073f68..4828725 100644
--- a/res/layout/filtershow_category_panel_new.xml
+++ b/res/layout/filtershow_category_panel_new.xml
@@ -16,22 +16,24 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
+              xmlns:custom="http://schemas.android.com/apk/res/org.codeaurora.gallery"
               android:orientation="horizontal"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
-              android:background="@color/filtershow_categoryview_background">
+              android:background="@android:color/transparent">
 
     <HorizontalScrollView
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
+            android:background="@android:color/transparent"
             android:scrollbars="none" >
 
         <com.android.gallery3d.filtershow.category.CategoryTrack
                 android:id="@+id/listItems"
                 android:layout_width="match_parent"
                 android:layout_height="@dimen/category_panel_height"
+                android:background="@android:color/transparent"
                 custom:iconSize="@dimen/category_panel_icon_size"
                 android:divider="@android:color/transparent"
                 android:dividerPadding="8dip"
@@ -45,4 +47,4 @@
             android:layout_height="@dimen/category_panel_height"
             android:src="@drawable/filtershow_add"/>
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/filtershow_category_panel_two.xml b/res/layout/filtershow_category_panel_two.xml
new file mode 100644
index 0000000..e807c88
--- /dev/null
+++ b/res/layout/filtershow_category_panel_two.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:theme="@android:style/Theme.DeviceDefault"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:background="@android:color/transparent"
+              android:orientation="vertical">
+    <LinearLayout xmlns:custom="http://schemas.android.com/apk/res/org.codeaurora.gallery"
+                  android:orientation="horizontal"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:background="@color/edit_actionbar_background">
+
+        <HorizontalScrollView
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:background="@android:color/transparent"
+            android:scrollbars="none" >
+
+            <com.android.gallery3d.filtershow.category.CategoryTrack
+                android:id="@+id/listItems"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/category_panel_height"
+                android:background="@android:color/transparent"
+                custom:iconSize="@dimen/category_panel_icon_size"
+                android:divider="@android:color/transparent"
+                android:dividerPadding="8dip"
+                />
+
+        </HorizontalScrollView>
+
+        <com.android.gallery3d.filtershow.category.IconView
+            android:id="@+id/addButton"
+            android:layout_width="@dimen/category_panel_height"
+            android:layout_height="@dimen/category_panel_height"
+            android:src="@drawable/filtershow_add"/>
+
+    </LinearLayout>
+
+    <FrameLayout
+        android:id="@+id/bottom_panel"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/category_actionbar_panel_height"
+        android:background="@color/edit_actionbar_background"
+        android:visibility="visible">
+
+        <ImageButton
+            android:id="@+id/cancel"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="?android:attr/actionBarItemBackground"
+            android:src="@drawable/cancel" />
+
+        <TextView
+            android:id="@+id/editor_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="16sp"
+            android:textColor="#fff"
+            android:layout_gravity="center"/>
+
+        <ImageButton
+            android:id="@+id/done"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="?android:attr/actionBarItemBackground"
+            android:layout_gravity="right"
+            android:src="@drawable/done" />
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/filtershow_color_picker.xml b/res/layout/filtershow_color_picker.xml
index e56bc0d..482c463 100644
--- a/res/layout/filtershow_color_picker.xml
+++ b/res/layout/filtershow_color_picker.xml
@@ -17,21 +17,21 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
-              android:background="@color/background_main_toolbar">
+              android:background="@color/albumset_background">
 
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                   android:orientation="vertical"
                   android:id="@+id/RelativeLayout1"
                   android:layout_width="match_parent"
                   android:layout_height="match_parent"
-                  android:background="@color/background_main_toolbar">
+                  android:background="@color/albumset_background">
 
         <com.android.gallery3d.filtershow.colorpicker.ColorCompareView
                 android:id="@+id/btnSelect"
                 android:layout_width="match_parent"
                 android:layout_height="32dp"
-                android:layout_marginLeft="20dp"
-                android:layout_marginRight="20dp"
+                android:layout_marginStart="20dp"
+                android:layout_marginEnd="20dp"
                 android:layout_marginTop="20dp"
                 android:layout_marginBottom="0dp"
                 />
@@ -40,7 +40,7 @@
                 android:layout_width="match_parent"
                 android:layout_height="256dp"
                 android:layout_marginTop="0dp"
-                android:layout_marginRight="1dp"/>
+                android:layout_marginEnd="1dp"/>
 
         <com.android.gallery3d.filtershow.colorpicker.ColorHueView
                 android:id="@+id/ColorHueView"
@@ -66,7 +66,7 @@
                     android:background="@android:color/transparent"
                     android:layout_weight=".1"
                     android:gravity="center"
-                    android:src="@drawable/ic_menu_cancel_holo_light"
+                    android:src="@drawable/cancel2"
                     android:textSize="18dip"/>
 
             <ImageView
@@ -81,7 +81,7 @@
                     android:layout_weight=".1"
                     android:background="@android:color/transparent"
                     android:gravity="center"
-                    android:src="@drawable/ic_menu_done_holo_light"
+                    android:src="@drawable/done2"
                     android:textSize="18dip"/>
         </LinearLayout>
     </LinearLayout>
diff --git a/res/layout/filtershow_control_action_slider.xml b/res/layout/filtershow_control_action_slider.xml
index 34eac1e..01d5e12 100644
--- a/res/layout/filtershow_control_action_slider.xml
+++ b/res/layout/filtershow_control_action_slider.xml
@@ -19,7 +19,8 @@
     xmlns:app="http://schemas.android.com/apk/res/com.example.imagefilterharness"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="horizontal" >
+    android:orientation="horizontal"
+    android:gravity="center" >
 
     <ImageButton
         android:id="@+id/leftActionButton"
@@ -29,8 +30,9 @@
         android:scaleType="centerInside"
         android:layout_weight="0"
         android:background="@drawable/filtershow_button_background"
-        android:src="@drawable/filtershow_addpoint"
-        android:paddingBottom="8dp"  />
+        android:src="@drawable/addspot"
+        android:paddingBottom="8dp"
+        android:paddingStart="14dp"  />
 
     <SeekBar
         android:id="@+id/controlValueSeekBar"
@@ -48,8 +50,9 @@
         android:scaleType="centerInside"
         android:layout_weight="0"
         android:background="@drawable/filtershow_button_background"
-        android:src="@drawable/ic_menu_trash_holo_light"
-        android:paddingBottom="8dp"  />
+        android:src="@drawable/delete"
+        android:paddingBottom="8dp"
+        android:paddingEnd="14dp"  />
 
 </LinearLayout>
 
diff --git a/res/layout/filtershow_control_color_chooser.xml b/res/layout/filtershow_control_color_chooser.xml
index 5bfe460..18ac83d 100644
--- a/res/layout/filtershow_control_color_chooser.xml
+++ b/res/layout/filtershow_control_color_chooser.xml
@@ -19,68 +19,64 @@
     xmlns:app="http://schemas.android.com/apk/res/com.example.imagefilterharness"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical|center_horizontal"
     android:orientation="horizontal" >
+
     <LinearLayout
-            android:id="@+id/listColors"
-            android:layout_weight="5"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
+        android:id="@+id/listColors"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="16dp"
+        android:orientation="horizontal" >
 
         <Button
-                android:id="@+id/draw_color_button01"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:background="@drawable/filtershow_color_picker_circle"
-                android:layout_marginRight="4dp"/>
+            android:id="@+id/draw_color_button01"
+            android:layout_width="@dimen/color_button_width"
+            android:layout_height="@dimen/color_button_height"
+            android:layout_marginEnd="22dp"
+            android:background="@drawable/filtershow_color_picker_circle" />
 
         <Button
-                android:id="@+id/draw_color_button02"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:background="@drawable/filtershow_color_picker_circle"
-                android:layout_marginRight="4dp"/>
+            android:id="@+id/draw_color_button02"
+            android:layout_width="@dimen/color_button_width"
+            android:layout_height="@dimen/color_button_height"
+            android:layout_marginEnd="22dp"
+            android:background="@drawable/filtershow_color_picker_circle" />
 
         <Button
-                android:id="@+id/draw_color_button03"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:background="@drawable/filtershow_color_picker_circle"
-                android:layout_marginRight="4dp"/>
+            android:id="@+id/draw_color_button03"
+            android:layout_width="@dimen/color_button_width"
+            android:layout_height="@dimen/color_button_height"
+            android:layout_marginEnd="22dp"
+            android:background="@drawable/filtershow_color_picker_circle" />
 
         <Button
-                android:id="@+id/draw_color_button04"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:background="@drawable/filtershow_color_picker_circle"
-                android:layout_marginRight="4dp"/>
+            android:id="@+id/draw_color_button04"
+            android:layout_width="@dimen/color_button_width"
+            android:layout_height="@dimen/color_button_height"
+            android:layout_marginEnd="22dp"
+            android:background="@drawable/filtershow_color_picker_circle" />
 
         <Button
-                android:id="@+id/draw_color_button05"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_height="wrap_content"
-                android:background="@drawable/filtershow_color_picker_circle"
-                android:layout_marginRight="4dp"/>
-
+            android:id="@+id/draw_color_button05"
+            android:layout_width="@dimen/color_button_width"
+            android:layout_height="@dimen/color_button_height"
+            android:layout_marginEnd="22dp"
+            android:background="@drawable/filtershow_color_picker_circle" />
     </LinearLayout>
 
     <FrameLayout
-            android:background="@color/background_main_toolbar"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center">
-    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:layout_marginRight="16dp" >
+
+        <Button
             android:id="@+id/draw_color_popupbutton"
             android:layout_width="wrap_content"
-            android:layout_gravity="center"
             android:layout_height="wrap_content"
-            android:background="@drawable/ic_action_overflow"
-            />
+            android:layout_gravity="center"
+            android:background="@drawable/more2" />
     </FrameLayout>
-</LinearLayout>
 
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_control_style_chooser.xml b/res/layout/filtershow_control_style_chooser.xml
index 9588ea2..d0004ff 100644
--- a/res/layout/filtershow_control_style_chooser.xml
+++ b/res/layout/filtershow_control_style_chooser.xml
@@ -18,7 +18,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res/com.example.imagefilterharness"
     android:layout_width="match_parent"
-    android:layout_height="32dp"
+    android:layout_height="wrap_content"
     android:orientation="horizontal" >
             <HorizontalScrollView
                 android:id="@+id/scrollList"
diff --git a/res/layout/filtershow_control_title_slider.xml b/res/layout/filtershow_control_title_slider.xml
index 584e015..23a5978 100644
--- a/res/layout/filtershow_control_title_slider.xml
+++ b/res/layout/filtershow_control_title_slider.xml
@@ -23,13 +23,13 @@
 
     <TextView
         android:id="@+id/controlName"
-        android:layout_gravity="left"
-        android:layout_marginLeft="8dip" />
+        android:layout_gravity="start"
+        android:layout_marginStart="8dip" />
 
     <TextView
         android:id="@+id/controlValue"
-        android:layout_gravity="right"
-        android:layout_marginRight="8dip"
+        android:layout_gravity="end"
+        android:layout_marginEnd="8dip"
         android:textStyle="bold" />
 
     <SeekBar
diff --git a/res/layout/filtershow_cp_custom_title.xml b/res/layout/filtershow_cp_custom_title.xml
index cef8b6c..5d7ed92 100644
--- a/res/layout/filtershow_cp_custom_title.xml
+++ b/res/layout/filtershow_cp_custom_title.xml
@@ -21,6 +21,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center"
-    android:layout_marginLeft="20dp"
-    android:layout_marginRight="20dp" >
+    android:layout_marginStart="20dp"
+    android:layout_marginEnd="20dp" >
 </TextView>
\ No newline at end of file
diff --git a/res/layout/filtershow_crop_button.xml b/res/layout/filtershow_crop_button.xml
index b42d6b6..22c467e 100644
--- a/res/layout/filtershow_crop_button.xml
+++ b/res/layout/filtershow_crop_button.xml
@@ -24,4 +24,4 @@
     android:background="@drawable/filtershow_button_background"
     android:scaleType="centerInside"
     android:visibility="gone"
-    android:text="@string/aspectNone_effect" />
\ No newline at end of file
+    android:text="@string/aspectFree_effect" />
diff --git a/res/layout/filtershow_default_edittext.xml b/res/layout/filtershow_default_edittext.xml
new file mode 100644
index 0000000..9af4eb7
--- /dev/null
+++ b/res/layout/filtershow_default_edittext.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <EditText
+        android:id="@+id/filtershow_default_edit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="19sp"
+        android:layout_marginRight="19sp"
+        android:focusable="true"
+        android:imeOptions="actionDone"
+        android:hint="@string/filter_name"
+        android:singleLine="true"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_dualcamera_editor.xml b/res/layout/filtershow_dualcamera_editor.xml
new file mode 100644
index 0000000..a845e25
--- /dev/null
+++ b/res/layout/filtershow_dualcamera_editor.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
+    android:id="@+id/editorDualCam"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_weight="1" >
+
+    <com.android.gallery3d.filtershow.imageshow.ImageDualCamera
+        android:id="@+id/imageDualCamera"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/res/layout/filtershow_editor_crop_landscape.xml b/res/layout/filtershow_editor_crop_landscape.xml
new file mode 100755
index 0000000..65be042
--- /dev/null
+++ b/res/layout/filtershow_editor_crop_landscape.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="@dimen/crop_panel_height_lanscape">
+
+    <FrameLayout
+        android:id="@+id/bottom_panel"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/crop_panel_height_lanscape"
+        android:background="@color/edit_actionbar_background"
+        android:layout_gravity="center_vertical">
+
+        <ImageButton
+            android:id="@+id/cancel"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="@color/edit_actionbar_background"
+            android:layout_gravity="left|center_vertical"
+            android:src="@drawable/cancel" />
+
+
+        <ImageButton
+            android:id="@+id/done"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="@color/edit_actionbar_background"
+            android:layout_gravity="right|center_vertical"
+            android:src="@drawable/done" />
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/crop_panel_height_lanscape"
+        android:background="@android:color/transparent"
+        android:layout_gravity="center"
+        android:clickable="true"
+        android:layout_marginStart="@dimen/category_actionbar_panel_height"
+        android:layout_marginEnd="@dimen/category_actionbar_panel_height"
+        android:orientation="horizontal">
+
+        <LinearLayout
+            android:id="@+id/leftPanel"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:orientation="vertical" >
+
+            <ImageButton
+                android:id="@+id/leftButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size_landscape"
+                android:scaleType="centerInside"
+                android:background="@android:color/transparent" />
+
+            <TextView
+                android:id="@+id/leftText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/centerPanel"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:orientation="vertical">
+
+            <ImageButton
+                android:id="@+id/centerButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size_landscape"
+                android:scaleType="centerInside"
+                android:background="@android:color/transparent" />
+
+            <TextView
+                android:id="@+id/centerText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/rightPanel"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:clickable="true"
+            android:layout_gravity="center_vertical"
+            android:background="@android:color/transparent"
+            android:orientation="vertical">
+
+            <ImageButton
+                android:id="@+id/rightButton"
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/crop_icon_size_landscape"
+                android:scaleType="centerInside"
+                android:background="@android:color/transparent" />
+
+            <TextView
+                android:id="@+id/rightText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:clickable="true"
+                android:background="@android:color/transparent"
+                android:layout_marginTop="@dimen/crop_text_margin_padding"
+                android:textColor="#ffffff"
+                android:textSize="12sp" />
+        </LinearLayout>
+    </LinearLayout>
+
+
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_editor_panel.xml b/res/layout/filtershow_editor_panel.xml
index 9953996..4f31770 100644
--- a/res/layout/filtershow_editor_panel.xml
+++ b/res/layout/filtershow_editor_panel.xml
@@ -18,105 +18,65 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/top"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
+    android:layout_height="match_parent"
     android:orientation="vertical"
+    android:background="@color/bottom_panel_background_color"
     android:visibility="visible" >
 
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
+    <Button
+        android:id="@+id/toggle_state"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:background="@color/background_main_toolbar"
+        android:text="@string/imageState"
+        android:visibility="gone"/>
+
+    <!-- <View -->
+    <!-- android:layout_width="match_parent" -->
+    <!-- android:layout_height="1dip" -->
+    <!-- android:background="@color/toolbar_separation_line" /> -->
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
+        android:layout_height="match_parent"
+        android:orientation="vertical" >
 
         <LinearLayout
-                android:id="@+id/controlArea"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_alignParentBottom="true"
-                android:visibility="visible">
+            android:id="@+id/controlArea"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_alignParentBottom="true"
+            android:orientation="horizontal"
+            android:gravity="center"
+            android:visibility="visible" >
+
+<!--             <TextView -->
+<!--                 android:id="@+id/tvFilterName" -->
+<!--                 android:layout_width="@dimen/swap_button_width" -->
+<!--                 android:layout_height="@dimen/swap_button_height" -->
+<!--                 android:text="@string/apply_effect" -->
+<!--                 android:layout_gravity="left" -->
+<!--                 android:textColor="@color/white" -->
+<!--                 android:textSize="20sp"  -->
+<!--                 android:layout_weight="1"/> -->
 
             <SeekBar
-                    android:id="@+id/primarySeekBar"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center_vertical"
-                    style="@style/FilterShowSlider"/>
-
+                android:id="@+id/primarySeekBar"
+                style="@style/FilterShowSlider"
+                android:layout_width="@dimen/seekbar_width_filter"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical|center_horizontal"
+                android:layout_weight="1"
+                android:layout_marginLeft="54dp"
+                android:layout_marginRight="54dp" />
         </LinearLayout>
 
-        <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="48dip"
-                android:background="@color/background_main_toolbar"
-                android:orientation="horizontal"
-                android:baselineAligned="false"
-                android:visibility="visible">
-
-            <ImageButton
-                    android:id="@+id/cancelFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="left|center_vertical"
-                    android:background="@android:color/transparent"
-                    android:layout_weight=".1"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_cancel_holo_light"
-                    android:textSize="18dip"/>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <LinearLayout
-                    android:id="@+id/panelAccessoryViewList"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="horizontal"
-                    android:visibility="visible">
-
-                <com.android.gallery3d.filtershow.editors.SwapButton
-                        android:id="@+id/applyEffect"
-                        android:layout_width="fill_parent"
-                        android:layout_height="fill_parent"
-                        android:layout_gravity="center"
-                        android:background="@android:color/transparent"
-                        android:text="@string/apply_effect"
-                        android:textSize="18dip"
-                        android:drawableEnd="@drawable/filtershow_menu_marker_rtl"
-                        android:textAllCaps="true"
-                        />
-
-            </LinearLayout>
-
-            <ImageView
-                    android:layout_width="2dp"
-                    android:layout_height="fill_parent"
-                    android:src="@drawable/filtershow_vertical_bar"/>
-
-            <ImageButton
-                    android:id="@+id/applyFilter"
-                    android:layout_width="wrap_content"
-                    android:layout_height="fill_parent"
-                    android:layout_gravity="right|center_vertical"
-                    android:layout_weight=".1"
-                    android:background="@android:color/transparent"
-                    android:gravity="center"
-                    android:src="@drawable/ic_menu_done_holo_light"
-                    android:textSize="18dip"/>
-        </LinearLayout>
-
-        <FrameLayout android:id="@+id/state_panel_container"
-                     android:layout_width="match_parent"
-                     android:layout_height="wrap_content"
-                     android:visibility="visible" />
-
+        <FrameLayout
+            android:id="@+id/state_panel_container"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:visibility="gone" />
     </LinearLayout>
 
 </LinearLayout>
diff --git a/res/layout/filtershow_export_dialog.xml b/res/layout/filtershow_export_dialog.xml
index 4e13f39..971260b 100644
--- a/res/layout/filtershow_export_dialog.xml
+++ b/res/layout/filtershow_export_dialog.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
      Copyright (C) 2013 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,113 +13,99 @@
      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="wrap_content"
-              android:divider="?android:dividerVertical"
-              android:showDividers="middle">
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal|center_vertical"
-        android:layout_margin="7dp"
-        android:text="@string/select_output_settings"/>
-
-    <GridLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:alignmentMode="alignBounds"
-        android:useDefaultMargins="true"
-        android:columnOrderPreserved="false"
-        android:columnCount="5">
-
-        <TextView
-                android:text="@string/size"
-                android:layout_marginLeft="8dp"
-                android:layout_gravity="start|center_vertical"/>
-
-        <EditText
-                android:id="@+id/editableWidth"
-                android:layout_gravity="right|center_vertical"
-                android:layout_width="100dp"
-                android:inputType="number"/>
-
-        <TextView
-                android:text="@string/x"
-                android:layout_gravity="center"/>
-
-        <EditText
-                android:id="@+id/editableHeight"
-                android:layout_gravity="left|center_vertical"
-                android:layout_width="100dp"
-                android:inputType="number"/>
-
-        <TextView
-                android:id="@+id/estimadedSize"
-                android:layout_marginRight="8dp"
-                android:layout_gravity="end|center_vertical"/>
-
-        <LinearLayout
-                android:layout_columnSpan="5"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-
-            <TextView
-                android:text="@string/quality"
-                android:layout_width="wrap_content"
-                android:layout_height="fill_parent"
-                android:layout_margin="8dp" />
-
-            <SeekBar
-                android:id="@+id/qualitySeekBar"
-                android:layout_margin="8dp"
-                android:layout_gravity="center"
-                android:max="100"
-                android:progress="100"
-                android:layout_height="wrap_content"
-                android:layout_width="0dp"
-                android:layout_weight="1"
-                android:layout_columnSpan="3"
-                android:minWidth="250dp" />
-
-            <TextView
-                android:id="@+id/qualityTextView"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_margin="8dp"
-                android:layout_gravity="end|center_vertical" />
-
-        </LinearLayout>
-
-
-    </GridLayout>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
 
     <LinearLayout
-            android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:padding="?android:attr/dialogPreferredPadding">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal|center_vertical"
+            android:text="@string/select_output_settings"
+            android:textColor="@color/albumset_label_background"
+            android:textSize="16sp" />
+
+        <GridLayout
             android:layout_width="match_parent"
-            android:layout_height="48dp"
-            style="?android:attr/buttonBarStyle">
+            android:layout_height="wrap_content"
+            android:layout_marginTop="8dp"
+            android:alignmentMode="alignBounds"
+            android:columnCount="5"
+            android:columnOrderPreserved="false"
+            android:orientation="horizontal">
 
-        <Button
-                android:id="@+id/cancel"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/cancel"
-                style="?android:attr/buttonBarButtonStyle" />
+            <TextView
+                android:layout_gravity="start|center_vertical"
+                android:layout_marginEnd="8dp"
+                android:text="@string/size"
+                android:textColor="@color/albumlist_label_title"
+                android:textSize="16sp" />
 
-        <Button
-                android:id="@+id/done"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:text="@string/done"
-                style="?android:attr/buttonBarButtonStyle"/>
+            <EditText
+                android:id="@+id/editableWidth"
+                android:layout_width="70dp"
+                android:layout_gravity="right|center_vertical"
+                android:gravity="center"
+                android:inputType="number" />
 
+            <TextView
+                android:layout_gravity="center"
+                android:text="@string/x"
+                android:textColor="@color/albumlist_label_title" />
+
+            <EditText
+                android:id="@+id/editableHeight"
+                android:layout_width="70dp"
+                android:layout_gravity="left|center_vertical"
+                android:gravity="center"
+                android:inputType="number" />
+
+            <TextView
+                android:id="@+id/estimadedSize"
+                android:layout_gravity="end|center_vertical"
+                android:textColor="@color/albumlist_label_title"
+                android:textSize="16sp" />
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_columnSpan="5"
+                android:layout_marginTop="16dp">
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="fill_parent"
+                    android:text="@string/quality"
+                    android:textColor="@color/albumlist_label_title"
+                    android:textSize="16sp" />
+
+                <SeekBar
+                    android:id="@+id/qualitySeekBar"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_columnSpan="3"
+                    android:layout_gravity="center"
+                    android:layout_weight="1"
+                    android:max="100"
+                    android:minWidth="250dp"
+                    android:progress="100" />
+
+                <TextView
+                    android:id="@+id/qualityTextView"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="end|center_vertical"
+                    android:textColor="@color/albumlist_label_title"
+                    android:textSize="16sp" />
+            </LinearLayout>
+        </GridLayout>
     </LinearLayout>
 
-</LinearLayout>
+</ScrollView>
+
diff --git a/res/layout/filtershow_history_panel.xml b/res/layout/filtershow_history_panel.xml
index 392e39c..992d05a 100644
--- a/res/layout/filtershow_history_panel.xml
+++ b/res/layout/filtershow_history_panel.xml
@@ -53,7 +53,7 @@
                 android:id="@+id/resetOperationsButton"
                 style="@style/FilterShowHistoryButton"
                 android:gravity="center"
-                android:text="@string/reset" />
+                android:text="@string/back_to_original" />
 
         <Button
                 android:id="@+id/saveOperationsButton"
diff --git a/res/layout/filtershow_info_panel.xml b/res/layout/filtershow_info_panel.xml
index 43878b6..552fef2 100644
--- a/res/layout/filtershow_info_panel.xml
+++ b/res/layout/filtershow_info_panel.xml
@@ -19,8 +19,8 @@
               android:minWidth="340dp"
               android:layout_height="match_parent"
               android:orientation="vertical"
-              android:background="@color/background_main_toolbar"
-              android:padding="16dp">
+              android:background="@color/albumset_background"
+              android:padding="24dp">
 
     <ScrollView
             android:layout_width="match_parent"
@@ -35,29 +35,34 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     android:orientation="horizontal"
+                    android:weightSum="1"
                     >
 
                 <TextView
                         android:id="@+id/imageName"
                         style="?android:textAppearanceSmall"
                         android:textStyle="bold"
-                        android:textColor="#80ffffff"
+                        android:textSize="16sp"
+                        android:textColor="@color/albumlist_label_title"
                         android:layout_gravity="start"
-                        android:layout_width="wrap_content"
+                        android:layout_width="0dp"
                         android:layout_height="wrap_content"
-                        android:layout_weight="1"
-                        android:gravity="start"/>
+                        android:gravity="start"
+                        android:ellipsize="end"
+                        android:layout_weight="0.65"
+                        android:maxLines="1"/>
 
                 <TextView
                         android:id="@+id/imageSize"
                         style="?android:textAppearanceSmall"
                         android:textAllCaps="true"
-                        android:textColor="#80ffffff"
+                        android:textSize="16sp"
+                        android:textColor="@color/albumlist_label_title"
                         android:textStyle="bold"
                         android:layout_gravity="end"
+                        android:layout_weight="0.35"
                         android:layout_width="0dp"
                         android:layout_height="wrap_content"
-                        android:layout_weight="1"
                         android:gravity="end"/>
 
             </LinearLayout>
@@ -74,7 +79,7 @@
                         android:layout_width="0dp"
                         android:layout_height="196dp"
                         android:scaleType="centerCrop"
-                        android:layout_marginRight="16dp"
+                        android:layout_marginEnd="16dp"
                         android:background="@null"
 
                         />
@@ -91,8 +96,9 @@
                     style="?android:textAppearanceLarge"
                     android:id="@+id/exifLabel"
                     android:textStyle="bold"
-                    android:textColor="#fff"
-                    android:layout_marginTop="16dp"
+                    android:textSize="20sp"
+                    android:textColor="@color/filtershow_info_text"
+                    android:layout_marginTop="24dp"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_gravity="start"
@@ -102,8 +108,11 @@
                     android:id="@+id/exifData"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="16dp"
+                    android:layout_marginTop="20dp"
+                    android:textSize="16sp"
+                    android:textColor="@color/albumlist_label_title"
                     android:layout_gravity="start"
+                    android:layout_marginBottom="32dp"
                     />
         </LinearLayout>
     </ScrollView>
diff --git a/res/layout/filtershow_main_panel.xml b/res/layout/filtershow_main_panel.xml
index d3400fa..74d0e0d 100644
--- a/res/layout/filtershow_main_panel.xml
+++ b/res/layout/filtershow_main_panel.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
+     Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+     Not a Contribution
+
      Copyright (C) 2013 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,13 +19,13 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:baselineAligned="false"
-              android:orientation="vertical"
-              android:animateLayoutChanges="false"
-              android:visibility="visible"
-              android:background="@color/background_main_toolbar" >
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:animateLayoutChanges="false"
+    android:baselineAligned="false"
+    android:orientation="vertical"
+    android:visibility="visible"
+    android:background="@android:color/transparent" >
 
     <FrameLayout android:id="@+id/state_panel_container"
                  android:layout_width="match_parent"
@@ -34,69 +37,18 @@
     <FrameLayout android:id="@+id/category_panel_container"
                  android:layout_width="match_parent"
                  android:visibility="visible"
-                 android:layout_height="0dip"
-                 android:layout_gravity="center"
+                 android:layout_height="wrap_content"
+                 android:layout_gravity="center_horizontal"
+                 android:paddingRight="5dp"
+                 android:paddingLeft="5dp"
+                 android:background="@color/crop_panel_background_color"
                  android:layout_weight="1"/>
 
-    <View
-            android:background="@color/toolbar_separation_line"
-            android:layout_height="1dip"
-            android:layout_width="match_parent"/>
-
-    <com.android.gallery3d.filtershow.CenteredLinearLayout
-            xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
-            android:id="@+id/bottom_panel"
+    <FrameLayout
+            android:id="@+id/bottom_panel_container"
             android:layout_width="match_parent"
-            android:layout_height="48dip"
-            android:layout_gravity="center|bottom"
-            custom:max_width="400dip"
-            android:orientation="vertical">
-
-        <LinearLayout android:layout_width="wrap_content"
-                      android:layout_height="match_parent"
-                      android:background="@color/background_main_toolbar">
-
-            <ImageButton
-                    android:id="@+id/fxButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_effects"/>
-
-            <ImageButton
-                    android:id="@+id/borderButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_border"/>
-
-            <ImageButton
-                    android:id="@+id/geometryButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_fix"/>
-
-            <ImageButton
-                    android:id="@+id/colorsButton"
-                    android:layout_width="@dimen/thumbnail_size"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:background="@drawable/filtershow_button_background"
-                    android:padding="2dip"
-                    android:scaleType="centerInside"
-                    android:src="@drawable/ic_photoeditor_color"/>
-
-        </LinearLayout>
-
-    </com.android.gallery3d.filtershow.CenteredLinearLayout>
-
-</LinearLayout>
\ No newline at end of file
+            android:layout_height="@dimen/bottom_panel_height"
+            android:visibility="visible"
+            android:layout_gravity="center_horizontal"
+            android:layout_weight="1"/>
+</LinearLayout>
diff --git a/res/layout/filtershow_presets_dialog.xml b/res/layout/filtershow_presets_dialog.xml
new file mode 100644
index 0000000..72db913
--- /dev/null
+++ b/res/layout/filtershow_presets_dialog.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="253dp"
+    android:layout_height="425dp"
+    android:background="#EFEFEF">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="26dp"
+        android:paddingTop="22dp"
+        android:orientation="horizontal">
+
+        <ImageView
+            android:id="@+id/icon_tools"
+            android:layout_width="21dp"
+            android:layout_height="20dp"
+            android:src="@drawable/icon_tools"/>
+
+        <TextView
+            android:id="@+id/dialog_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="11dp"
+            android:textColor="#000000"
+            android:textSize="16sp"
+            android:text="@string/filtershow_dialog_title"/>
+    </LinearLayout>
+
+    <TextView
+        android:id="@+id/dialog_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="21dp"
+        android:layout_marginEnd="33dp"
+        android:layout_marginTop="22dp"
+        android:textSize="13sp"
+        android:textColor="#000000"
+        android:text="@string/filtershow_dialog_content"/>
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:gravity="center_horizontal"
+        android:layout_marginTop="64dp"
+        android:layout_marginStart="21dp"
+        android:layout_marginEnd="21dp">
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/original_photo"
+                android:layout_width="105dp"
+                android:layout_height="79dp"
+                android:layout_gravity="center"
+                android:src="@drawable/ref_city" />
+
+            <TextView
+                android:id="@+id/original"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:textColor="#000000"
+                android:textSize="9sp"
+                android:text="@string/filtershow_dialog_original_photo" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical">
+
+            <ImageView
+                android:id="@+id/filter_photo"
+                android:layout_width="105dp"
+                android:layout_height="79dp"
+                android:layout_gravity="center"
+                android:src="@drawable/ref_flowers" />
+
+            <TextView
+                android:id="@+id/filter"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:textColor="#000000"
+                android:textSize="9sp"
+                android:text="@string/filtershow_dialog_apply_photo"/>
+        </LinearLayout>
+    </LinearLayout>
+
+    <CheckBox
+        android:id="@+id/filtershow_check_box"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="25dp"
+        android:layout_marginTop="60dp"
+        android:textSize="13sp"
+        android:text="@string/filtershow_dialog_checkbox" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="2px"
+        android:layout_marginTop="18dp"
+        android:background="#D8D8D8" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="110dp"
+        android:layout_marginEnd="14dp">
+
+        <Button
+            android:id="@+id/cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/cancel"
+            android:textSize="13dp"
+            style="?android:attr/buttonBarButtonStyle" />
+
+        <Button
+            android:id="@+id/ok"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/ok_continue"
+            android:textSize="13dp"
+            style="?android:attr/buttonBarButtonStyle" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_seekbar.xml b/res/layout/filtershow_seekbar.xml
index 54a874d..12f8a7c 100644
--- a/res/layout/filtershow_seekbar.xml
+++ b/res/layout/filtershow_seekbar.xml
@@ -15,18 +15,39 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@android:style/Theme.DeviceDefault"
     android:id="@+id/top"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical"
     android:visibility="visible" >
 
+    <ImageButton
+        android:id="@+id/slider_cancel"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
+        android:src="@drawable/cancel"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:background="?android:attr/actionBarItemBackground" />
+
+    <ImageButton
+        android:id="@+id/slider_save"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
+        android:src="@drawable/done"
+        android:layout_centerVertical="true"
+        android:layout_alignParentRight="true"
+        android:background="?android:attr/actionBarItemBackground" />
+
     <SeekBar
         android:id="@+id/primarySeekBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
         style="@style/FilterShowSlider"
-        android:visibility="gone" />
-
-</LinearLayout>
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_centerVertical="true"
+        android:layout_toRightOf="@id/slider_cancel"
+        android:layout_toLeftOf="@id/slider_save"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"/>
+</RelativeLayout>
diff --git a/res/layout/filtershow_splashscreen.xml b/res/layout/filtershow_splashscreen.xml
index 06958ca..8d7fe3e 100644
--- a/res/layout/filtershow_splashscreen.xml
+++ b/res/layout/filtershow_splashscreen.xml
@@ -23,7 +23,7 @@
               android:padding="10dip">
 
 <ProgressBar android:id="@+id/progress_bar"
-             android:layout_alignParentRight="true"
+             android:layout_alignParentEnd="true"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:gravity="center_vertical"
diff --git a/res/layout/filtershow_state_panel_new.xml b/res/layout/filtershow_state_panel_new.xml
index b199695..ac67ccb 100644
--- a/res/layout/filtershow_state_panel_new.xml
+++ b/res/layout/filtershow_state_panel_new.xml
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              xmlns:custom="http://schemas.android.com/apk/res/com.android.gallery3d"
+              xmlns:custom="http://schemas.android.com/apk/res/org.codeaurora.gallery"
               android:orientation="vertical"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
-              android:background="@color/background_main_toolbar">
+              android:background="@color/edit_actionbar_background">
 
     <View
             android:background="@color/toolbar_separation_line"
diff --git a/res/layout/filtershow_trueportrait_editor_panel.xml b/res/layout/filtershow_trueportrait_editor_panel.xml
new file mode 100644
index 0000000..13b8212
--- /dev/null
+++ b/res/layout/filtershow_trueportrait_editor_panel.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@android:color/transparent"
+    android:orientation="vertical" >
+
+    <FrameLayout
+        android:id="@+id/bottom_panel"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/category_actionbar_panel_height"
+        android:background="@color/edit_actionbar_background" >
+
+        <ImageButton
+            android:id="@+id/cancel"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:background="@color/edit_actionbar_background"
+            android:src="@drawable/cancel" />
+
+        <LinearLayout
+            android:id="@+id/brush_size"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:clickable="true">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:padding="3dp"
+                android:text="@string/brush_size"
+                android:textColor="#fff"
+                android:textSize="16sp" />
+            <ImageView
+                android:id="@+id/brush_size_sm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:padding="3dp"
+                android:src="@drawable/tp_brush_sm" />
+            <ImageView
+                android:id="@+id/brush_size_med"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:padding="3dp"
+                android:src="@drawable/tp_brush_med" />
+            <ImageView
+                android:id="@+id/brush_size_large"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:padding="3dp"
+                android:src="@drawable/tp_brush_large" />
+        </LinearLayout>
+
+        <ImageButton
+            android:id="@+id/done"
+            android:layout_width="@dimen/category_actionbar_panel_height"
+            android:layout_height="@dimen/category_actionbar_panel_height"
+            android:layout_gravity="right"
+            android:background="@color/edit_actionbar_background"
+            android:src="@drawable/done" />
+    </FrameLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/filtershow_trueportrait_mask_editor.xml b/res/layout/filtershow_trueportrait_mask_editor.xml
new file mode 100644
index 0000000..1de55d8
--- /dev/null
+++ b/res/layout/filtershow_trueportrait_mask_editor.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:iconbutton="http://schemas.android.com/apk/res/com.android.gallery3d"
+    android:id="@+id/truePortraitMaskEditor"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:paddingBottom="@dimen/category_actionbar_panel_height"
+    android:paddingTop="@dimen/category_actionbar_panel_height" >
+
+    <com.android.gallery3d.filtershow.imageshow.ImageTruePortraitMask
+        android:id="@+id/imageTruePortraitMask"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+</FrameLayout>
diff --git a/res/layout/filtershow_watermark.xml b/res/layout/filtershow_watermark.xml
new file mode 100644
index 0000000..fe986cc
--- /dev/null
+++ b/res/layout/filtershow_watermark.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/root_layout"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <ImageView
+        android:id="@+id/image"
+        android:layout_width="80dp"
+        android:layout_height="80dp"
+        android:layout_gravity="left" />
+
+    <EditText
+        android:id="@+id/edit"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@null"
+        android:cursorVisible="true"
+        android:layout_gravity="left"
+        android:inputType="textNoSuggestions"
+        android:textColor="@color/watermark_text_color"
+        android:textColorHint="@color/watermark_text_color"
+        android:textSize="16sp" />
+
+</FrameLayout>
diff --git a/res/layout/gallery_main.xml b/res/layout/gallery_main.xml
new file mode 100755
index 0000000..3cbc1e8
--- /dev/null
+++ b/res/layout/gallery_main.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/drawerLayout"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:fitsSystemWindows="true">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <RelativeLayout
+            android:id="@+id/gallery_root"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_above="@+id/bottom_navigation">
+
+            <!-- Toolbar -->
+            <include layout="@layout/toolbar" />
+
+            <!-- Main content -->
+            <include layout="@layout/gl_root_group" />
+
+        </RelativeLayout>
+
+        <!-- Bottom bar -->
+        <com.google.android.material.bottomnavigation.BottomNavigationView
+            android:id="@+id/bottom_navigation"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@color/primary"
+            android:layout_alignParentBottom="true"
+            app:menu="@menu/navigation_items"
+            app:itemBackground="@color/primary"
+            app:itemIconTint="@drawable/item_bg"
+            app:itemTextColor="@drawable/item_bg" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/layout/gl_root_group.xml b/res/layout/gl_root_group.xml
index 76ff33b..6302171 100644
--- a/res/layout/gl_root_group.xml
+++ b/res/layout/gl_root_group.xml
@@ -15,12 +15,18 @@
 -->
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <com.android.gallery3d.ui.GLRootView
+
+    <RelativeLayout
+        android:id="@+id/gl_parent_layout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <com.android.gallery3d.ui.GLRootView
             android:id="@+id/gl_root_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"/>
+    </RelativeLayout>
     <View android:id="@+id/gl_root_cover"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:background="@android:color/black"/>
+            android:background="#fafafa"/>
 </merge>
diff --git a/res/layout/ingest_date_tile.xml b/res/layout/ingest_date_tile.xml
index 8cd63e9..b042213 100644
--- a/res/layout/ingest_date_tile.xml
+++ b/res/layout/ingest_date_tile.xml
@@ -61,4 +61,4 @@
             android:fontFamily="sans-serif"
             android:textColor="@color/ingest_date_tile_text" />
     </GridLayout>
-</com.android.gallery3d.ingest.ui.DateTileView>
\ No newline at end of file
+</com.android.gallery3d.ingest.ui.DateTileView>
diff --git a/res/layout/ingest_fullsize.xml b/res/layout/ingest_fullsize.xml
index d57c4ae..91a3fcf 100644
--- a/res/layout/ingest_fullsize.xml
+++ b/res/layout/ingest_fullsize.xml
@@ -41,4 +41,4 @@
         android:layout_alignParentRight="true"
         android:text="@string/ingest_import" />
 
-</com.android.gallery3d.ingest.ui.MtpFullscreenView>
\ No newline at end of file
+</com.android.gallery3d.ingest.ui.MtpFullscreenView>
diff --git a/res/layout/main.xml b/res/layout/main.xml
index 08e5959..e26e0fc 100644
--- a/res/layout/main.xml
+++ b/res/layout/main.xml
@@ -13,8 +13,8 @@
     <FrameLayout android:id="@+id/footer"
             android:visibility="gone"
             android:layout_alignParentBottom="true"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentEnd="true"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"/>
 </RelativeLayout>
diff --git a/res/layout/manage_offline_bar.xml b/res/layout/manage_offline_bar.xml
index 5c71613..6996180 100644
--- a/res/layout/manage_offline_bar.xml
+++ b/res/layout/manage_offline_bar.xml
@@ -39,23 +39,23 @@
     </RelativeLayout>
     <RelativeLayout android:layout_width="fill_parent"
                 android:layout_height="@dimen/manage_cache_bottom_height"
-                android:paddingLeft="16dp"
-                android:paddingRight="16dp"
+                android:paddingStart="16dp"
+                android:paddingEnd="16dp"
                 android:background="#1f1f1f">
         <TextView android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:text="@string/make_available_offline"
             android:textSize="14sp"
-            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
             android:layout_centerVertical="true"
             android:gravity="center_vertical"
-            android:drawableLeft="@drawable/ic_menu_make_offline"
+            android:drawableStart="@drawable/ic_menu_make_offline"
             android:drawablePadding="3dp"/>
         <Button android:id="@+id/done"
             android:layout_width="74dp"
             android:layout_height="match_parent"
             android:text="@string/done"
             android:textSize="14sp"
-            android:layout_alignParentRight="true"/>
+            android:layout_alignParentEnd="true"/>
     </RelativeLayout>
 </LinearLayout>
diff --git a/res/layout/mediapicker_list_item.xml b/res/layout/mediapicker_list_item.xml
new file mode 100644
index 0000000..12f8c63
--- /dev/null
+++ b/res/layout/mediapicker_list_item.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/container"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <com.android.gallery3d.filtershow.mediapicker.SelectedImageView
+        android:id="@+id/thumbnail"
+        android:layout_width="@dimen/picker_photo_size"
+        android:layout_height="@dimen/picker_photo_size"
+        android:layout_gravity="center"
+        android:scaleType="centerCrop" />
+</RelativeLayout>
diff --git a/res/layout/mediapicker_panel.xml b/res/layout/mediapicker_panel.xml
new file mode 100644
index 0000000..fb34ebf
--- /dev/null
+++ b/res/layout/mediapicker_panel.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<com.android.gallery3d.filtershow.mediapicker.MediaPicker
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout
+        android:id="@+id/mediapicker_slidestrip"
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:gravity="bottom|center"
+        android:orientation="horizontal"
+        android:background="#00000000" >
+        <ImageButton
+            android:id="@+id/arrow"
+            android:layout_width="60dp"
+            android:layout_height="30dp"
+            android:layout_alignParentBottom="true"
+            android:src="@drawable/arrow"
+            android:background="#00000000" />
+    </LinearLayout>
+
+    <com.android.photos.views.HeaderGridView
+        android:id="@+id/grid"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:cacheColorHint="@android:color/transparent"
+        android:columnWidth="@dimen/picker_photo_size"
+        android:drawSelectorOnTop="true"
+        android:fadingEdge="none"
+        android:gravity="center"
+        android:horizontalSpacing="@dimen/picker_photo_spacing"
+        android:listSelector="@android:color/transparent"
+        android:numColumns="auto_fit"
+        android:paddingLeft="5dp"
+        android:paddingRight="5dp"
+        android:scrollbars="none"
+        android:stretchMode="columnWidth"
+        android:verticalSpacing="@dimen/picker_photo_spacing"/>
+
+    <LinearLayout
+        android:id="@+id/mediapicker_tabstrip"
+        android:layout_width="match_parent"
+        android:layout_height="60dp"
+        android:orientation="horizontal"
+        android:background="#c0000000" >
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <ImageButton
+                android:id="@+id/btn_no"
+                android:layout_width="60dp"
+                android:layout_height="60dp"
+                android:layout_centerVertical="true"
+                android:layout_alignParentLeft="true"
+                android:src="@drawable/cancel"
+                android:background="#00000000" />
+            <ImageButton
+                android:id="@+id/btn_yes"
+                android:layout_width="60dp"
+                android:layout_height="60dp"
+                android:layout_centerVertical="true"
+                android:layout_alignParentRight="true"
+                android:src="@drawable/done"
+                android:background="#00000000" />
+        </RelativeLayout>
+    </LinearLayout>
+
+</com.android.gallery3d.filtershow.mediapicker.MediaPicker>
diff --git a/res/layout/menu_indicators_keyguard.xml b/res/layout/menu_indicators_keyguard.xml
index 7a8795d..b8f36cf 100644
--- a/res/layout/menu_indicators_keyguard.xml
+++ b/res/layout/menu_indicators_keyguard.xml
@@ -21,7 +21,7 @@
     <ImageView
         android:id="@+id/menu_scenemode_indicator"
         style="@style/MenuIndicator"
-        android:layout_gravity="left|top"
+        android:layout_gravity="start|top"
         android:src="@drawable/ic_indicator_sce_off" />
 
     <ImageView
@@ -33,13 +33,13 @@
     <ImageView
         android:id="@+id/menu_flash_indicator"
         style="@style/MenuIndicator"
-        android:layout_gravity="right|top"
+        android:layout_gravity="end|top"
         android:src="@drawable/ic_indicator_flash_auto" />
 
     <ImageView
         android:id="@+id/menu_exposure_indicator"
         style="@style/MenuIndicator"
-        android:layout_gravity="left|bottom"
+        android:layout_gravity="start|bottom"
         android:src="@drawable/ic_indicator_ev_0" />
 
     <ImageView
@@ -51,7 +51,7 @@
     <ImageView
         android:id="@+id/menu_wb_indicator"
         style="@style/MenuIndicator"
-        android:layout_gravity="right|bottom"
+        android:layout_gravity="end|bottom"
         android:src="@drawable/ic_indicator_wb_off" />
 
 </FrameLayout>
\ No newline at end of file
diff --git a/res/layout/movie_view.xml b/res/layout/movie_view.xml
index 75b8dfd..2679e38 100644
--- a/res/layout/movie_view.xml
+++ b/res/layout/movie_view.xml
@@ -19,9 +19,23 @@
         android:background="@android:color/black"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
-    <VideoView android:id="@+id/surface_view"
-            android:visibility="invisible"
+
+    <org.codeaurora.gallery3d.video.CodeauroraVideoView android:id="@+id/surface_view"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_centerInParent="true" />
+
+    <View
+        android:id="@+id/surface_view_cover"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@android:color/black"/>
+
+    <ImageView
+        android:id="@+id/img_live"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        android:src="@drawable/ic_media_live"/>
 </RelativeLayout>
diff --git a/res/layout/photo_frame.xml b/res/layout/photo_frame.xml
index deadaeb..ede942f 100755
--- a/res/layout/photo_frame.xml
+++ b/res/layout/photo_frame.xml
@@ -19,8 +19,30 @@
         android:layout_height="match_parent"
         android:paddingTop="4dp"
         android:paddingBottom="23dp"
-        android:paddingLeft="12dp"
-        android:paddingRight="12dp">
+        android:paddingStart="12dp"
+        android:paddingEnd="12dp">
+
+    <RelativeLayout
+        android:id="@+id/appwidget_empty_photo"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone">
+
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:background="@drawable/appwidget_photo_border">
+
+            <TextView
+                android:id="@id/appwidget_photo_item"
+                android:layout_width="@dimen/stack_photo_width"
+                android:layout_height="@dimen/stack_photo_height"
+                android:gravity="center"
+                android:text="@string/appwidget_empty_text"
+                android:textColor="@android:color/black" />
+        </FrameLayout>
+    </RelativeLayout>
     <ImageView android:id="@+id/photo"
             android:layout_gravity="center"
             android:layout_width="wrap_content"
diff --git a/res/layout/photopage_bottom_controls.xml b/res/layout/photopage_bottom_controls.xml
index f3226e6..cd8e8a7 100644
--- a/res/layout/photopage_bottom_controls.xml
+++ b/res/layout/photopage_bottom_controls.xml
@@ -1,50 +1,44 @@
 <?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/photopage_bottom_controls"
-        android:padding="10dp"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:orientation="horizontal"
-        android:visibility="gone">
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_edit"
-                android:src="@drawable/ic_menu_edit_holo_dark"
-                android:background="@drawable/photopage_bottom_button_background"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="15dp"
-                android:paddingRight="15dp"
-                android:visibility="gone"/>
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_panorama"
-                android:src="@drawable/ic_view_photosphere"
-                android:background="@drawable/transparent_button_background"
-                android:layout_width="70dp"
-                android:layout_height="70dp"
-                android:layout_centerHorizontal="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="5dp"
-                android:paddingRight="5dp"
-                android:visibility="gone"/>
-        <ImageButton
-                android:id="@+id/photopage_bottom_control_tiny_planet"
-                android:src="@drawable/ic_menu_tiny_planet"
-                android:background="@drawable/photopage_bottom_button_background"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_alignParentBottom="true"
-                android:paddingTop="5dp"
-                android:paddingBottom="5dp"
-                android:paddingLeft="15dp"
-                android:paddingRight="15dp"
-                android:visibility="gone"/>
-</RelativeLayout>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/photopage_bottom_controls"
+    android:theme="@android:style/Theme.DeviceDefault"
+    android:layout_width="match_parent"
+    android:layout_height="56dp"
+    android:layout_alignParentBottom="true"
+    android:layout_gravity="bottom"
+    android:background="@color/photo_page_bottom_panel"
+    android:gravity="bottom"
+    android:orientation="horizontal"
+    android:visibility="gone" >
+
+    <ImageButton
+        android:id="@+id/photopage_bottom_control_edit"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_weight="1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:src="@drawable/edit"
+        android:visibility="gone" />
+
+    <ImageButton
+        android:id="@+id/photopage_bottom_control_share"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_weight="1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:src="@drawable/share"
+        android:visibility="gone" />
+
+    <ImageButton
+        android:id="@+id/photopage_bottom_control_delete"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_weight="1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:src="@drawable/delete"
+        android:visibility="gone" />
+
+</LinearLayout>
diff --git a/res/layout/photopage_progress_bar.xml b/res/layout/photopage_progress_bar.xml
index 778feb3..1acbd77 100644
--- a/res/layout/photopage_progress_bar.xml
+++ b/res/layout/photopage_progress_bar.xml
@@ -4,12 +4,12 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:padding="25dp"
         android:visibility="invisible">
         <View
                 android:id="@+id/photopage_progress_background"
-                android:background="#ff000000"
+                android:background="@color/black"
                 android:layout_width="match_parent"
                 android:layout_height="8dp"
                 android:layout_alignParentBottom="true"
@@ -19,21 +19,21 @@
                 android:background="#ff33b5e5"
                 android:layout_width="10dp"
                 android:layout_height="8dp"
-                android:layout_alignParentLeft="true"
+                android:layout_alignParentStart="true"
                 android:layout_alignParentBottom="true"
                 android:visibility="visible"/>
         <TextView
                 android:id="@+id/photopage_progress_bar_text"
                 android:text="@string/pano_progress_text"
-                android:textColor="#ffffffff"
+                android:textColor="@color/white"
                 android:textSize="14dp"
-                android:shadowColor="#ff000000"
+                android:shadowColor="@color/black"
                 android:shadowDx="0"
                 android:shadowDy="0"
                 android:shadowRadius="2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
+                android:layout_alignParentEnd="true"
                 android:layout_above="@id/photopage_progress_background"
                 android:paddingBottom="8dp"
                 android:visibility="visible"/>
diff --git a/res/layout/popup_list_item.xml b/res/layout/popup_list_item.xml
index 5a87af7..a2f7c31 100644
--- a/res/layout/popup_list_item.xml
+++ b/res/layout/popup_list_item.xml
@@ -19,10 +19,12 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+    android:textSize="18sp"
+    android:textColor="@color/black_transparent_4"
     android:singleLine="true"
     android:gravity="center_vertical"
-    android:paddingLeft="16dp"
-    android:paddingRight="16dp"
-    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
     android:minWidth="196dp"
 />
diff --git a/res/layout/rotate_dialog.xml b/res/layout/rotate_dialog.xml
index c62ce91..c1cf866 100644
--- a/res/layout/rotate_dialog.xml
+++ b/res/layout/rotate_dialog.xml
@@ -44,8 +44,8 @@
                 <TextView android:id="@+id/rotate_dialog_title"
                         style="@style/TextAppearance.DialogWindowTitle"
                         android:gravity="center_vertical"
-                        android:layout_marginLeft="16dip"
-                        android:layout_marginRight="16dip"
+                        android:layout_marginStart="16dip"
+                        android:layout_marginEnd="16dip"
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
                         android:minHeight="64dp"/>
diff --git a/res/layout/setting_list.xml b/res/layout/setting_list.xml
new file mode 100644
index 0000000..51ad753
--- /dev/null
+++ b/res/layout/setting_list.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+    <!--
+        /* * 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. */
+    -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <ListView android:id="@android:id/list" android:layout_width="match_parent"
+        android:layout_height="0px" android:layout_weight="1"
+        android:paddingStart="16dip" android:paddingEnd="16dip"
+        android:paddingTop="0dp" android:paddingBottom="0dp"
+        android:clipToPadding="false" android:scrollbarStyle="outsideOverlay"
+        android:drawSelectorOnTop="false" android:cacheColorHint="@android:color/transparent"
+        android:listPreferredItemHeight="48dp"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
+</LinearLayout>
+
diff --git a/res/layout/three_d_button.xml b/res/layout/three_d_button.xml
new file mode 100644
index 0000000..eb8366d
--- /dev/null
+++ b/res/layout/three_d_button.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/three_d_button"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_marginTop="100dp"
+    android:layout_marginEnd="50dp"
+    android:layout_alignParentTop="true"
+    android:layout_alignParentEnd="true"
+    android:layout_gravity="bottom"
+    android:orientation="horizontal"
+    android:theme="@android:style/Theme.DeviceDefault"
+    android:visibility="gone">
+
+    <ImageButton
+        android:id="@+id/three_dimensional"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:layout_weight="1"
+        android:background="?android:attr/actionBarItemBackground"
+        android:src="@drawable/three_d"
+        android:visibility="visible" />
+</LinearLayout>
diff --git a/res/layout/time_interval_picker.xml b/res/layout/time_interval_picker.xml
index d2a9462..daab1c8 100644
--- a/res/layout/time_interval_picker.xml
+++ b/res/layout/time_interval_picker.xml
@@ -40,8 +40,8 @@
             android:orientation="horizontal"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingLeft="16dip"
-            android:paddingRight="16dip" >
+            android:paddingStart="16dip"
+            android:paddingEnd="16dip" >
 
         <!-- time interval duration -->
         <NumberPicker
@@ -57,7 +57,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_weight="2"
-                android:layout_marginLeft="20dip"
+                android:layout_marginStart="20dip"
                 android:focusable="false" />
 
     </LinearLayout>
diff --git a/res/layout/time_interval_popup.xml b/res/layout/time_interval_popup.xml
index 9cf224a..2eadf90 100644
--- a/res/layout/time_interval_popup.xml
+++ b/res/layout/time_interval_popup.xml
@@ -38,8 +38,8 @@
                     android:layout_width="wrap_content"
                     android:layout_height="match_parent"
                     android:layout_weight="0"
-                    android:layout_marginRight="8dp"
-                    android:layout_gravity="right|center_vertical" />
+                    android:layout_marginEnd="8dp"
+                    android:layout_gravity="end|center_vertical" />
         </LinearLayout>
 
         <View style="@style/PopupTitleSeparator" />
@@ -54,8 +54,8 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:paddingTop="16dip"
-                    android:paddingLeft="16dip"
-                    android:paddingRight="16dip"
+                    android:paddingStart="16dip"
+                    android:paddingEnd="16dip"
                     android:paddingBottom="16dip"
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:text="@string/set_time_interval_help"/>
diff --git a/res/layout/toolbar.xml b/res/layout/toolbar.xml
new file mode 100755
index 0000000..00270e3
--- /dev/null
+++ b/res/layout/toolbar.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<com.google.android.material.appbar.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:theme="@style/ToolbarTheme">
+
+    <Toolbar
+        android:id="@+id/toolbar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:background="@color/primary"
+        android:elevation="8dp"
+        android:titleTextAppearance="@style/ToolbarTitleStyle"
+        android:popupTheme="@style/ToolbarPopUpTheme" />
+
+</com.google.android.material.appbar.AppBarLayout>
diff --git a/res/layout/trim_menu.xml b/res/layout/trim_menu.xml
index e233392..79a0f88 100644
--- a/res/layout/trim_menu.xml
+++ b/res/layout/trim_menu.xml
@@ -18,15 +18,23 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_centerVertical="true">
-    <TextView
-        android:id="@+id/start_trim"
-        android:layout_marginLeft="8dp"
+    <ImageView
+        android:id="@+id/exit_trim"
+        android:background="?android:attr/actionBarItemBackground"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
+        android:src="@drawable/cancel"/>
+    <TextView
+        android:id="@+id/start_trim"
+        android:background="?android:attr/selectableItemBackgroundBorderless"
+        android:layout_marginStart="8dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:text="@string/save"
         android:textAllCaps="true"
-        android:textSize="14sp"
+        android:layout_gravity="end|center_vertical"
+        android:textSize="16sp"
+        android:textColor="@color/primary_text"
         android:gravity="left|center_vertical"
-        android:drawableLeft="@drawable/menu_save_photo"
         android:drawablePadding="8dp" />
 </FrameLayout>
diff --git a/res/layout/undo_bar.xml b/res/layout/undo_bar.xml
index 33ec91d..bd4274d 100644
--- a/res/layout/undo_bar.xml
+++ b/res/layout/undo_bar.xml
@@ -27,5 +27,5 @@
     <TextView android:id="@+id/undo_button"
             style="@style/UndoButton"
             android:text="@string/undo"
-            android:drawableLeft="@drawable/ic_menu_revert_holo_dark"/>
+            android:drawableStart="@drawable/ic_menu_revert_holo_dark"/>
 </LinearLayout>
diff --git a/res/layout/view_gif_image.xml b/res/layout/view_gif_image.xml
new file mode 100644
index 0000000..976549a
--- /dev/null
+++ b/res/layout/view_gif_image.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <LinearLayout
+            android:id="@+id/image_absoluteLayout"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent">
+        <ImageView android:id="@+id/image_display_area"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:clickable="true">
+        </ImageView>
+    </LinearLayout>
+
+</RelativeLayout>
diff --git a/res/layout/viewfinder_labels_video.xml b/res/layout/viewfinder_labels_video.xml
index cfe3b02..1ed7f39 100644
--- a/res/layout/viewfinder_labels_video.xml
+++ b/res/layout/viewfinder_labels_video.xml
@@ -21,7 +21,7 @@
     <TextView android:id="@+id/recording_time"
             style="@style/OnViewfinderLabel"
             android:gravity="center"
-            android:drawableLeft="@drawable/ic_recording_indicator"
+            android:drawableStart="@drawable/ic_recording_indicator"
             android:drawablePadding="5dp"
             android:visibility="gone" />
     <TextView android:id="@+id/time_lapse_label"
diff --git a/res/menu/album.xml b/res/menu/album.xml
index 4db0e51..4b76b69 100644
--- a/res/menu/album.xml
+++ b/res/menu/album.xml
@@ -15,17 +15,20 @@
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/action_camera"
-            android:icon="@drawable/ic_menu_camera_holo_light"
-            android:title="@string/switch_to_camera"
-            android:showAsAction="ifRoom" />
+        android:icon="@drawable/camera"
+        android:title="@string/switch_to_camera"
+        android:showAsAction="ifRoom" />
     <item android:id="@+id/action_slideshow"
-            android:icon="@drawable/ic_menu_slideshow_holo_light"
-            android:title="@string/slideshow"
-            android:showAsAction="never" />
+        android:icon="@drawable/slideshow"
+        android:title="@string/slideshow"
+        android:showAsAction="ifRoom" />
     <item android:id="@+id/action_select"
-            android:title="@string/select_item"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_group_by"
-            android:title="@string/group_by"
-            android:showAsAction="never"/>
+        android:icon="@drawable/ic_selection"
+        android:title="@string/select_item"
+        android:showAsAction="ifRoom" />
+<!--     <item android:id="@+id/action_group_by" -->
+<!--             android:title="@string/group_by" -->
+<!--             android:showAsAction="never"/> -->
+     <item android:id="@+id/action_view_type"
+       android:showAsAction="never" />
 </menu>
diff --git a/res/menu/albumset.xml b/res/menu/albumset.xml
index 8ac8cbb..b21bf3d 100644
--- a/res/menu/albumset.xml
+++ b/res/menu/albumset.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Google Inc.
+<!-- Copyright (c) 2014, The Linux Foundation. All rights reserved.
+     Not a Contribution.
+
+     Copyright (C) 2010 Google Inc.
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,23 +18,25 @@
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/action_camera"
-            android:icon="@drawable/ic_menu_camera_holo_light"
-            android:title="@string/switch_to_camera"
-            android:showAsAction="ifRoom" />
+        android:icon="@drawable/camera"
+        android:title="@string/switch_to_camera"
+        android:showAsAction="ifRoom" />
     <item android:id="@+id/action_select"
-            android:title="@string/select_album"
-            android:showAsAction="never" />
+        android:icon="@drawable/ic_selection"
+        android:title="@string/select_album"
+        android:showAsAction="ifRoom" />
     <item android:id="@+id/action_manage_offline"
             android:title="@string/make_available_offline"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_sync_picasa_albums"
-            android:title="@string/sync_picasa_albums"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_settings"
-            android:title="@string/settings"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_general_help"
-            android:title="@string/help"
             android:visible="false"
             android:showAsAction="never" />
+    <!-- <item android:id="@+id/action_settings"
+        android:title="@string/settings"
+        android:showAsAction="never" /> -->
+    <item android:id="@+id/action_general_help"
+        android:title="@string/help"
+        android:visible="false"
+        android:showAsAction="never" />
+    <item android:id="@+id/action_more_image"
+        android:title="@string/more_image"
+        android:showAsAction="never" />
 </menu>
diff --git a/res/menu/filtershow_activity_menu.xml b/res/menu/filtershow_activity_menu.xml
index bb0b094..e99826e 100644
--- a/res/menu/filtershow_activity_menu.xml
+++ b/res/menu/filtershow_activity_menu.xml
@@ -1,34 +1,27 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
     <item
         android:id="@+id/menu_share"
-        android:actionProviderClass="android.widget.ShareActionProvider"
         android:showAsAction="never"
-        android:enabled="false"
         android:visible="false"
         android:title="@string/share"/>
-    <item
-        android:id="@+id/undoButton"
-        android:icon="@drawable/filtershow_button_undo"
-        android:showAsAction="always"
-        android:title="@string/filtershow_undo"/>
-    <item
-        android:id="@+id/redoButton"
-        android:icon="@drawable/filtershow_button_redo"
-        android:showAsAction="always"
-        android:title="@string/filtershow_redo"/>
+<!--     <item -->
+<!--         android:id="@+id/undoButton" -->
+<!--         android:icon="@drawable/filtershow_button_undo" -->
+<!--         android:showAsAction="always" -->
+<!--         android:title="@string/filtershow_undo"/> -->
+<!--     <item -->
+<!--         android:id="@+id/redoButton" -->
+<!--         android:icon="@drawable/filtershow_button_redo" -->
+<!--         android:showAsAction="always" -->
+<!--         android:title="@string/filtershow_redo"/> -->
     <item
         android:id="@+id/resetHistoryButton"
-        android:title="@string/reset"/>
-    <item
-        android:id="@+id/showInfoPanel"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/filtershow_show_info_panel" />
-    <item
-        android:id="@+id/showImageStateButton"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/show_imagestate_panel" />
+        android:title="@string/back_to_original"/>
+<!--     <item -->
+<!--         android:id="@+id/showImageStateButton" -->
+<!--         android:showAsAction="never" -->
+<!--         android:visible="true" -->
+<!--         android:title="@string/show_imagestate_panel" /> -->
     <item
         android:id="@+id/manageUserPresets"
         android:showAsAction="never"
@@ -39,9 +32,4 @@
         android:showAsAction="never"
         android:visible="true"
         android:title="@string/export_image" />
-    <item
-        android:id="@+id/printButton"
-        android:showAsAction="never"
-        android:visible="true"
-        android:title="@string/print_image"/>
 </menu>
diff --git a/res/menu/filtershow_menu_crop.xml b/res/menu/filtershow_menu_crop.xml
index f8ba3df..94b06be 100644
--- a/res/menu/filtershow_menu_crop.xml
+++ b/res/menu/filtershow_menu_crop.xml
@@ -26,7 +26,7 @@
             android:title="@string/aspect9to16_effect"/>
         <item
             android:id="@+id/crop_menu_none"
-            android:title="@string/aspectNone_effect"/>
+            android:title="@string/aspectFree_effect"/>
         <item
             android:id="@+id/crop_menu_original"
             android:title="@string/aspectOriginal_effect"/>
diff --git a/res/menu/filtershow_menu_edit.xml b/res/menu/filtershow_menu_edit.xml
new file mode 100644
index 0000000..afab8cd
--- /dev/null
+++ b/res/menu/filtershow_menu_edit.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/deleteButton"
+        android:title="@string/delete"/>
+    <item
+        android:id="@+id/renameButton"
+        android:title="@string/filtershow_preset_rename"/>
+</menu>
\ No newline at end of file
diff --git a/res/menu/filtershow_menu_fusion.xml b/res/menu/filtershow_menu_fusion.xml
new file mode 100644
index 0000000..f80349e
--- /dev/null
+++ b/res/menu/filtershow_menu_fusion.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+    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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+    WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+    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.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <group android:id="@+id/fusion_popupmenu" >
+        <item
+            android:id="@+id/fusion_menu_choose_segment"
+            android:title="@string/fusion_pick_point"/>
+        <item
+            android:id="@+id/fusion_menu_choose_underlay"
+            android:title="@string/fusion_pick_underlay"/>
+    </group>
+
+</menu>
\ No newline at end of file
diff --git a/res/menu/gallery_multiselect.xml b/res/menu/gallery_multiselect.xml
index d9365c1..685ae6b 100644
--- a/res/menu/gallery_multiselect.xml
+++ b/res/menu/gallery_multiselect.xml
@@ -12,8 +12,7 @@
     <item android:id="@+id/menu_share"
           android:title="@string/share"
           android:showAsAction="ifRoom"
-          android:visible="false"
-          android:actionProviderClass="android.widget.ShareActionProvider" />
+          android:visible="false" />
     <item android:id="@+id/menu_crop"
             android:title="@string/crop_action"
             android:visible="false"
@@ -30,4 +29,4 @@
             android:title="@string/set_as"
             android:visible="false"
             android:showAsAction="never" />
-</menu>
\ No newline at end of file
+</menu>
diff --git a/res/menu/movie.xml b/res/menu/movie.xml
index fde235c..ce3a100 100644
--- a/res/menu/movie.xml
+++ b/res/menu/movie.xml
@@ -18,6 +18,5 @@
             android:icon="@drawable/ic_menu_share_holo_light"
             android:title="@string/share"
             android:enabled="true"
-            android:actionProviderClass="android.widget.ShareActionProvider"
             android:showAsAction="ifRoom" />
 </menu>
diff --git a/res/menu/navigation_items.xml b/res/menu/navigation_items.xml
new file mode 100644
index 0000000..b4f39dc
--- /dev/null
+++ b/res/menu/navigation_items.xml
@@ -0,0 +1,11 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+     <item android:id="@+id/action_timeline"
+          android:title="@string/timeline_title"
+          android:icon="@drawable/ic_timeline" />
+     <item android:id="@+id/action_album"
+          android:title="@string/albums_title"
+          android:icon="@drawable/ic_album" />
+     <item android:id="@+id/action_videos"
+          android:title="@string/videos_title"
+          android:icon="@drawable/ic_video" />
+</menu>
diff --git a/res/menu/operation.xml b/res/menu/operation.xml
index d1791e2..0647cad 100644
--- a/res/menu/operation.xml
+++ b/res/menu/operation.xml
@@ -26,18 +26,16 @@
             android:icon="@drawable/ic_menu_share_holo_light"
             android:title="@string/share_panorama"
             android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
             android:showAsAction="ifRoom">
     </item>
     <item android:id="@+id/action_share"
-            android:icon="@drawable/ic_menu_share_holo_light"
+            android:icon="@drawable/multiselect_share"
             android:title="@string/share"
             android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="never">
+            android:showAsAction="ifRoom">
     </item>
     <item android:id="@+id/action_delete"
-            android:icon="@drawable/ic_menu_trash_holo_light"
+            android:icon="@drawable/multiselect_delete"
             android:title="@string/delete"
             android:visible="false"
             android:showAsAction="ifRoom" />
@@ -70,4 +68,9 @@
             android:title="@string/show_on_map"
             android:showAsAction="never"
             android:visible="false" />
+    <item android:id="@+id/action_drm_info"
+            android:title="@string/drm_license_info"
+            android:enabled="true"
+            android:visible="false"
+            android:showAsAction="never" />
 </menu>
diff --git a/res/menu/photo.xml b/res/menu/photo.xml
index bcd452e..b388d08 100644
--- a/res/menu/photo.xml
+++ b/res/menu/photo.xml
@@ -14,52 +14,50 @@
      limitations under the License.
 -->
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/action_import"
-            android:title="@string/Import"
-            android:icon="@drawable/ic_menu_ptp_holo_light"
-            android:showAsAction="always|withText"
-            android:visible="false" />
-    <!-- Ideally, showAsAction for share_panorama and share should be reversed.
-         But, if share_panorama is set to never, it doesn't seem to get promoted
-         to the action bar and stays on the overflow menu. -->
-    <item android:id="@+id/action_share_panorama"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share_panorama"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="ifRoom" />
-    <item android:id="@+id/action_share"
-            android:icon="@drawable/ic_menu_share_holo_light"
-            android:title="@string/share"
-            android:visible="false"
-            android:actionProviderClass="android.widget.ShareActionProvider"
-            android:showAsAction="never" />
-    <item android:id="@+id/action_delete"
-            android:icon="@drawable/ic_menu_trash_holo_light"
-            android:title="@string/delete"
-            android:visible="false"
-            android:showAsAction="never" />
+<!--     <item android:id="@+id/action_import" -->
+<!--             android:title="@string/Import" -->
+<!--             android:icon="@drawable/ic_menu_ptp_holo_light" -->
+<!--             android:showAsAction="always|withText" -->
+<!--             android:visible="false" /> -->
+<!--    Ideally, showAsAction for share_panorama and share should be reversed. -->
+<!--    But, if share_panorama is set to never, it doesn't seem to get promoted -->
+<!--          to the action bar and stays on the overflow menu. -->
+<!--     <item android:id="@+id/action_share_panorama" -->
+<!--             android:icon="@drawable/ic_menu_share_holo_light" -->
+<!--             android:title="@string/share_panorama" -->
+<!--             android:visible="false" -->
+<!--             android:showAsAction="ifRoom" /> -->
+<!--     <item android:id="@+id/action_share" -->
+<!--             android:icon="@drawable/ic_menu_share_holo_light" -->
+<!--             android:title="@string/share" -->
+<!--             android:visible="false" -->
+<!--             android:showAsAction="never" /> -->
+<!--     <item android:id="@+id/action_delete" -->
+<!--             android:icon="@drawable/ic_menu_trash_holo_light" -->
+<!--             android:title="@string/delete" -->
+<!--             android:visible="false" -->
+<!--             android:showAsAction="never" /> -->
     <item android:id="@+id/action_slideshow"
             android:icon="@drawable/ic_menu_slideshow_holo_light"
             android:title="@string/slideshow"
             android:showAsAction="never" />
-    <item android:id="@+id/action_edit"
-            android:title="@string/edit"
-            android:showAsAction="never"
-            android:visible="false" />
-    <item android:id="@+id/action_simple_edit"
-          android:title="@string/simple_edit"
-          android:showAsAction="never"
-          android:visible="false" />
-    <item android:id="@+id/action_rotate_ccw"
-            android:showAsAction="never"
-            android:title="@string/rotate_left" />
-    <item android:id="@+id/action_rotate_cw"
-            android:showAsAction="never"
-            android:title="@string/rotate_right" />
-    <item android:id="@+id/action_crop"
-            android:title="@string/crop_action"
-            android:showAsAction="never" />
+<!--     <item android:id="@+id/action_edit" -->
+<!--             android:title="@string/edit" -->
+<!--             android:showAsAction="never" -->
+<!--             android:visible="false" /> -->
+<!--     <item android:id="@+id/action_simple_edit" -->
+<!--           android:title="@string/simple_edit" -->
+<!--           android:showAsAction="never" -->
+<!--           android:visible="false" /> -->
+<!--     <item android:id="@+id/action_rotate_ccw" -->
+<!--             android:showAsAction="never" -->
+<!--             android:title="@string/rotate_left" /> -->
+<!--     <item android:id="@+id/action_rotate_cw" -->
+<!--             android:showAsAction="never" -->
+<!--             android:title="@string/rotate_right" /> -->
+<!--     <item android:id="@+id/action_crop" -->
+<!--             android:title="@string/crop_action" -->
+<!--             android:showAsAction="never" /> -->
     <item android:id="@+id/action_trim"
             android:title="@string/trim_action"
             android:showAsAction="never" />
@@ -78,4 +76,9 @@
     <item android:id="@+id/print"
           android:title="@string/print_image"
           android:showAsAction="never" />
+    <item android:id="@+id/action_drm_info"
+        android:title="@string/drm_license_info"
+        android:enabled="true"
+        android:visible="false"
+        android:showAsAction="never" />
 </menu>
diff --git a/res/mipmap-anydpi/ic_launcher.xml b/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 0000000..d8649ba
--- /dev/null
+++ b/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2018 The LineageOS Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@mipmap/ic_background"/>
+    <foreground android:drawable="@mipmap/ic_foreground"/>
+</adaptive-icon>
+
diff --git a/res/mipmap-anydpi/ic_launcher_gallery.xml b/res/mipmap-anydpi/ic_launcher_gallery.xml
deleted file mode 100644
index c4e9e75..0000000
--- a/res/mipmap-anydpi/ic_launcher_gallery.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@color/ic_launcher_gallery_background"/>
-    <foreground android:drawable="@mipmap/ic_launcher_gallery_foreground"/>
-</adaptive-icon>
\ No newline at end of file
diff --git a/res/mipmap-hdpi/ic_background.png b/res/mipmap-hdpi/ic_background.png
new file mode 100644
index 0000000..16bcdc5
--- /dev/null
+++ b/res/mipmap-hdpi/ic_background.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_foreground.png b/res/mipmap-hdpi/ic_foreground.png
new file mode 100644
index 0000000..9969295
--- /dev/null
+++ b/res/mipmap-hdpi/ic_foreground.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher_gallery_foreground.png b/res/mipmap-hdpi/ic_launcher_gallery_foreground.png
deleted file mode 100644
index 6db33c0..0000000
--- a/res/mipmap-hdpi/ic_launcher_gallery_foreground.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-mdpi/ic_background.png b/res/mipmap-mdpi/ic_background.png
new file mode 100644
index 0000000..bc97fa9
--- /dev/null
+++ b/res/mipmap-mdpi/ic_background.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_foreground.png b/res/mipmap-mdpi/ic_foreground.png
new file mode 100644
index 0000000..a11ed30
--- /dev/null
+++ b/res/mipmap-mdpi/ic_foreground.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_gallery_foreground.png b/res/mipmap-mdpi/ic_launcher_gallery_foreground.png
deleted file mode 100644
index de2c3bf..0000000
--- a/res/mipmap-mdpi/ic_launcher_gallery_foreground.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_background.png b/res/mipmap-xhdpi/ic_background.png
new file mode 100644
index 0000000..f12d9c0
--- /dev/null
+++ b/res/mipmap-xhdpi/ic_background.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_foreground.png b/res/mipmap-xhdpi/ic_foreground.png
new file mode 100644
index 0000000..a63937e
--- /dev/null
+++ b/res/mipmap-xhdpi/ic_foreground.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_gallery_foreground.png b/res/mipmap-xhdpi/ic_launcher_gallery_foreground.png
deleted file mode 100644
index fb79d35..0000000
--- a/res/mipmap-xhdpi/ic_launcher_gallery_foreground.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_background.png b/res/mipmap-xxhdpi/ic_background.png
new file mode 100644
index 0000000..5affeba
--- /dev/null
+++ b/res/mipmap-xxhdpi/ic_background.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_foreground.png b/res/mipmap-xxhdpi/ic_foreground.png
new file mode 100644
index 0000000..51c88b5
--- /dev/null
+++ b/res/mipmap-xxhdpi/ic_foreground.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_gallery_foreground.png b/res/mipmap-xxhdpi/ic_launcher_gallery_foreground.png
deleted file mode 100644
index 691a1ca..0000000
--- a/res/mipmap-xxhdpi/ic_launcher_gallery_foreground.png
+++ /dev/null
Binary files differ
diff --git a/res/mipmap-xxxhdpi/ic_background.png b/res/mipmap-xxxhdpi/ic_background.png
new file mode 100644
index 0000000..89d2ea5
--- /dev/null
+++ b/res/mipmap-xxxhdpi/ic_background.png
Binary files differ
diff --git a/res/mipmap-xxxhdpi/ic_foreground.png b/res/mipmap-xxxhdpi/ic_foreground.png
new file mode 100644
index 0000000..63a5fd2
--- /dev/null
+++ b/res/mipmap-xxxhdpi/ic_foreground.png
Binary files differ
diff --git a/res/mipmap-xxxhdpi/ic_launcher_gallery_foreground.png b/res/mipmap-xxxhdpi/ic_launcher_gallery_foreground.png
deleted file mode 100644
index 529f0ff..0000000
--- a/res/mipmap-xxxhdpi/ic_launcher_gallery_foreground.png
+++ /dev/null
Binary files differ
diff --git a/res/raw/sketch_bm.jpg b/res/raw/sketch_bm.jpg
new file mode 100644
index 0000000..a85e966
--- /dev/null
+++ b/res/raw/sketch_bm.jpg
Binary files differ
diff --git a/res/values-af/cm_strings.xml b/res/values-af/cm_strings.xml
new file mode 100644
index 0000000..30e47ab
--- /dev/null
+++ b/res/values-af/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tyd van opname</string>
+</resources>
diff --git a/res/values-af/codeaurora_strings.xml b/res/values-af/codeaurora_strings.xml
new file mode 100644
index 0000000..9b27638
--- /dev/null
+++ b/res/values-af/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Stap</string>
+    <string name="step_option_desc">Verpersoonlik vinnige vorentoe/terugspeel stap</string>
+    <string name="setp_option_three_second">3 sekondes</string>
+    <string name="setp_option_six_second">6 sekondes</string>
+    <string name="loop">"Omkring"</string>
+    <string name="single">"Enkel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Luidspreker AAN</string>
+    <string name="speaker_off">Luidspreker AF</string>
+    <string name="speaker_need_headset">Prop in oorfone om hierdie funksie te gebruik.</string>
+    <string name="single_track">"Enkele snit"</string>
+    <string name="input_url">"Sleutel URL in"</string>
+    <string name="streaming_settings">"Stroom instellings"</string>
+    <string name="next">"Volgende"</string>
+    <string name="previous">"Vorige"</string>
+    <string name="buffer_size">Buffer grootte</string>
+    <string name="apn">Voorkeur TPN</string>
+    <string name="rtp_min_port">Min poort</string>
+    <string name="rtp_max_port">Maks poort</string>
+    <string name="set_rtp_min_port">Stel min poort</string>
+    <string name="set_rtp_max_port">Stel maks poort</string>
+    <string name="set_buffer_size">Stel buffer grootte</string>
+    <string name="set_apn">Kies gewenste TPN</string>
+    <string name="setting">Instellings</string>
+    <string name="server_timeout_title">"Bediener tydverstreke"</string>
+    <string name="server_timeout_message">"Herkonnekteer met die bediener om die video te speel?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Verbinding het misluk, probeer weer om aan te sluit na %1$d\u2026"</string>
+    <string name="media_controller_live">Regstreeks</string>
+    <string name="media_controller_playing">Speel</string>
+    <string name="media_controller_connecting">Koppel\u2026</string>
+    <string name="bookmark_add">"Voeg boekmerk by"</string>
+    <string name="bookmark_display">"Wys boekmerk"</string>
+    <string name="bookmark_empty">"Geen boekmerk"</string>
+    <string name="bookmark_exist">"Boekmerk bestaan alreeds"</string>
+    <string name="bookmark_add_success">"Boekmerk bygevoeg"</string>
+    <string name="bookmark_list">"Boekmerke"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Ligging"</string>
+    <string name="delete_all">"Verwyder alles"</string>
+    <string name="default_title">"Standaard titel"</string>
+    <string name="more_image">Nog prente</string>
+    <string name="mute_nosupport">Kan nie klank afskakel: video nie ondersteun</string>
+    <string name="map_activity_not_found_err">Daar is geen kaart program geïnstalleer om die plek te wys nie.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video\'s</item>
+    </plurals>
+    <string name="cannot_share_items">Maks geselekteerde items vir deel is 300</string>
+    <string name="share_dialogue_title">Deel via</string>
+    <string name="no_faces">Geen gesigte</string>
+    <string name="fail_trim">Jammer, hierdie video lêer kan nie afgewerk word nie</string>
+    <string name="can_not_trim">Slegs mp4 en 3gp lêers kan afgewerk word</string>
+    <string name="drm_license_info">DRM lisensie inligting</string>
+    <string name="timeline_title">Tydlyn</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">Lysaansig</string>
+    <string name="tvEmptyAlbum">Geen foto\'s gevind</string>
+    <string name="tvEmptyVideos">Geen video\'s gevind</string>
+    <string name="text_makeup_whiten">Maak witter</string>
+    <string name="text_makeup_Soften">Versag</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Groot oë</string>
+    <string name="truescanner_normal">Normaal</string>
+    <string name="truescanner_white">Witbord</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Verwyder refleksie lig</string>
+    <string name="hazebuster_acts">Verwyder waas</string>
+    <string name="seestraight_acts">Kyk reguit</string>
+    <string name="seestraight_input_image_is_small">Invoer beeld is te klein om te verwerk.</string>
+    <string name="seestraight_process_fail">Kon nie die beeld verwerk nie.</string>
+    <string name="trim_video_exit_title">Verwerp wysigings?</string>
+    <string name="trim_video_exit_msg">Gooi veranderinge weg van hierdie video?</string>
+    <string name="trim_video_exit_discard">GOOI WEG</string>
+</resources>
diff --git a/res/values-ar/cm_strings.xml b/res/values-ar/cm_strings.xml
new file mode 100644
index 0000000..08a324c
--- /dev/null
+++ b/res/values-ar/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">مدة التسجيل</string>
+</resources>
diff --git a/res/values-ar/codeaurora_strings.xml b/res/values-ar/codeaurora_strings.xml
new file mode 100644
index 0000000..c04e44a
--- /dev/null
+++ b/res/values-ar/codeaurora_strings.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">خطوة</string>
+    <string name="step_option_desc">تخصيص خطوة التقديم/الترجيع السريع</string>
+    <string name="setp_option_three_second">3 ثوان</string>
+    <string name="setp_option_six_second">6 ثوانٍ</string>
+    <string name="loop">"تكرار"</string>
+    <string name="single">"واحد"</string>
+    <string name="stereo">"استيريو"</string>
+    <string name="speaker_on">تشغيل مكبّر الصوت</string>
+    <string name="speaker_off">إيقاف مكبّر الصوت</string>
+    <string name="speaker_need_headset">قم بتوصيل سماعات الرأس لاستخدام هذه الميزة.</string>
+    <string name="single_track">"أغنية واحدة"</string>
+    <string name="input_url">"أدخل عنوان URL"</string>
+    <string name="streaming_settings">"إعدادات التدفق"</string>
+    <string name="next">"التالي"</string>
+    <string name="previous">"السابق"</string>
+    <string name="buffer_size">حجم المخزن المؤقت</string>
+    <string name="apn">APN المفضل</string>
+    <string name="rtp_min_port">منفذ الحد الأدنى </string>
+    <string name="rtp_max_port">منفذ الحد الأقصى</string>
+    <string name="set_rtp_min_port">تعيين الحد الأدنى للمنفذ</string>
+    <string name="set_rtp_max_port">تعيين الحد الأقصى للمنفذ</string>
+    <string name="set_buffer_size">تعيين حجم المخزن المؤقت</string>
+    <string name="set_apn">حدد APN المفضل</string>
+    <string name="setting">إعدادات</string>
+    <string name="server_timeout_title">"مهلة الخادم"</string>
+    <string name="server_timeout_message">"هل تود إعادة الاتصال بالخادم لتشغيل الفيديو؟"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"فشل الاتصال، جاري محاولة إعادة الاتصال ب%1$d\u2026"</string>
+    <string name="media_controller_live">مباشر</string>
+    <string name="media_controller_playing">قيد التشغيل</string>
+    <string name="media_controller_connecting">جاري الاتصال\u2026</string>
+    <string name="bookmark_add">"إضافة إشارة مرجعية"</string>
+    <string name="bookmark_display">"عرض الإشارات المرجعية"</string>
+    <string name="bookmark_empty">"لا توجد إشارات مرجعية"</string>
+    <string name="bookmark_exist">"هذه الإشارة المرجعية موجودة بالفعل"</string>
+    <string name="bookmark_add_success">"تمت إضافة الإشارة المرجعية"</string>
+    <string name="bookmark_list">"الإشارات المرجعيّة"</string>
+    <string name="bookmark_title">"العنوان"</string>
+    <string name="bookmark_location">"الموقع"</string>
+    <string name="delete_all">"حذف الكل"</string>
+    <string name="default_title">"العنوان الافتراضي"</string>
+    <string name="more_image">مزيد من الصور</string>
+    <string name="mute_nosupport">لا يمكن كتم الصوت : الفيديو غير مدعوم</string>
+    <string name="map_activity_not_found_err">لا يوجد تطبيق خرائط مثبت لإظهار الموقع.</string>
+    <plurals name="number_of_videos">
+        <item quantity="zero">%1$d فيديوهات</item>
+        <item quantity="one">%1$d فيديو</item>
+        <item quantity="two">%1$d فيديوهات</item>
+        <item quantity="few">%1$d فيديوهات</item>
+        <item quantity="many">%1$d فيديوهات</item>
+        <item quantity="other">%1$d فيديوهات</item>
+    </plurals>
+    <string name="cannot_share_items">الحد الأقصى للعناصر المحددة للمشاركة هو 300</string>
+    <string name="share_dialogue_title">مشاركة عبر</string>
+    <string name="no_faces">لا يوجد وجوه</string>
+    <string name="fail_trim">عذراً، لا يمكن الاقتطاع من ملف الفيديو هذا</string>
+    <string name="can_not_trim">يمكن اقتطاع ملفات mp4 و 3gp فقط</string>
+    <string name="drm_license_info">معلومات ترخيص إدارة الحقوق الرقمية</string>
+    <string name="timeline_title">الجدول الزمني</string>
+    <string name="albums_title">الألبومات</string>
+    <string name="videos_title">الفيديوهات</string>
+    <string name="action_viewtype_list">عرض القائمة</string>
+    <string name="tvEmptyAlbum">لم يُعثر على صور</string>
+    <string name="tvEmptyVideos">لم يُعثر على فيديوهات</string>
+    <string name="text_makeup_whiten">تبييض</string>
+    <string name="text_makeup_Soften">تنعيم</string>
+    <string name="text_makeup_trimface">اقتطاع الوجه</string>
+    <string name="text_makeup_bigeye">تكبير العين</string>
+    <string name="truescanner_normal">عادي</string>
+    <string name="truescanner_white">سبورة بيضاء</string>
+    <string name="truescanner">ماسحة حقيقة</string>
+    <string name="truescanner_remove_glare">إزالة الوهج</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">نظر مستقيم</string>
+    <string name="seestraight_input_image_is_small">الصورة المدخلة صغيرة جداً للعملية.</string>
+    <string name="seestraight_process_fail">تعذر معالجة الصورة.</string>
+    <string name="trim_video_exit_title">تجاهل التغييرات؟</string>
+    <string name="trim_video_exit_msg">تجاهل التغييرات التي تم إجراؤها على هذا الفيديو؟</string>
+    <string name="trim_video_exit_discard">تجاهل</string>
+</resources>
diff --git a/res/values-as/cm_strings.xml b/res/values-as/cm_strings.xml
new file mode 100644
index 0000000..96c3438
--- /dev/null
+++ b/res/values-as/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">ৰেকৰ্ড সময়</string>
+</resources>
diff --git a/res/values-as/codeaurora_strings.xml b/res/values-as/codeaurora_strings.xml
new file mode 100644
index 0000000..58ba5dd
--- /dev/null
+++ b/res/values-as/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">পৰ্যায়</string>
+    <string name="step_option_desc">ফাষ্ট ফৰৱাৰ্ড/ ৰিৱাইণ্ড পদক্ষেপ অনুকূলিত কৰক</string>
+    <string name="setp_option_three_second">3 চেকেণ্ড</string>
+    <string name="setp_option_six_second">6 চেকেণ্ড</string>
+    <string name="loop">""লুপ""</string>
+    <string name="single">""একক""</string>
+    <string name="stereo">""ষ্টেৰীঅ""</string>
+    <string name="speaker_on">স্পিকাৰ অন</string>
+    <string name="speaker_off">স্পিকাৰ অফ</string>
+    <string name="speaker_need_headset">এই বৈশিষ্ট্যটো ব্যৱহাৰ কৰিবলৈ হেডফোন প্লাগ ইন কৰক</string>
+    <string name="single_track">""একক ট্ৰেক""</string>
+    <string name="input_url">"“URL প্ৰৱিষ্ট কৰক”"</string>
+    <string name="streaming_settings">""ষ্ট্ৰিমিং ছেটিংছ""</string>
+    <string name="next">""পৰৱৰ্তী""</string>
+    <string name="previous">""পূৰ্বৱৰ্তী""</string>
+    <string name="buffer_size">বাফাৰৰ আকাৰ</string>
+    <string name="apn">অগ্ৰাধিকাৰপ্ৰাপ্ত APN</string>
+    <string name="rtp_min_port">মিন পোৰ্ট</string>
+    <string name="rtp_max_port">মেক্স পোৰ্ট</string>
+    <string name="set_rtp_min_port">মিন পোৰ্ট ছেট কৰক</string>
+    <string name="set_rtp_max_port">মেক্স পোৰ্ট ছেট কৰক</string>
+    <string name="set_buffer_size">বাফাৰৰ আকাৰ ছেট কৰক</string>
+    <string name="set_apn">অগ্ৰাধিকাৰপ্ৰাপ্ত APN ছেট কৰক</string>
+    <string name="setting">ছেটিংছ</string>
+    <string name="server_timeout_title">""ছাৰ্ভাৰ টাইম আউট""</string>
+    <string name="server_timeout_message">"“ভিডিঅ' প্লে কৰিবলৈ ছাৰ্ভাৰলৈ পুনৰ সংযোগ কৰিব”?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"“সংযোগ ব্যৰ্থ হৈছে, %1$d\u2026 লৈ পুনৰ সংযোগ কৰিবলৈ চেষ্টা কৰি আছে""</string>
+    <string name="media_controller_live">লাইভ</string>
+    <string name="media_controller_playing">প্লে কৰি আছে</string>
+    <string name="media_controller_connecting">সংযোগ কৰি আছে\u2026</string>
+    <string name="bookmark_add">""বুকমাৰ্ক যোগ দিয়ক""</string>
+    <string name="bookmark_display">""বুকমাৰ্কসমূহ প্ৰদৰ্শন কৰক""</string>
+    <string name="bookmark_empty">""কোনো বুকমাৰ্কসমূহ নাই""</string>
+    <string name="bookmark_exist">"“বুকমাৰ্ক ইতিমধ্যে বিদ্যমান”"</string>
+    <string name="bookmark_add_success">"“বুকমাৰ্ক যোগ কৰা হৈছে”"</string>
+    <string name="bookmark_list">""বুকমাৰ্কসমূহ""</string>
+    <string name="bookmark_title">""শিৰোনামা""</string>
+    <string name="bookmark_location">""অৱস্থান""</string>
+    <string name="delete_all">""সকলোবোৰ মচি পেলাওঁক""</string>
+    <string name="default_title">""ডিফল্ট শিৰোনামা""</string>
+    <string name="more_image">অধিক প্ৰতিচ্ছবি</string>
+    <string name="mute_nosupport">মিউট কৰিব নোৱাৰি : ভিডিঅ\' সমৰ্থিত নহয়</string>
+    <string name="map_activity_not_found_err">অৱস্থান দেখুৱাবলৈ মেপ এপ্প্ ইনষ্টল কৰা নাই।</string>
+    <string name="fail_trim">দুঃখিত, এই ভিডিঅ\' চুটি কৰিব নোৱাৰি</string>
+    <string name="drm_license_info">DRM অনুজ্ঞাপত্ৰৰ তথ্য</string>
+</resources>
diff --git a/res/values-ast-rES/cm_strings.xml b/res/values-ast-rES/cm_strings.xml
new file mode 100644
index 0000000..b6fe794
--- /dev/null
+++ b/res/values-ast-rES/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Data de grabación</string>
+</resources>
diff --git a/res/values-ast-rES/codeaurora_strings.xml b/res/values-ast-rES/codeaurora_strings.xml
new file mode 100644
index 0000000..48ceb4d
--- /dev/null
+++ b/res/values-ast-rES/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Pasu</string>
+    <string name="step_option_desc">Personalizar el saltu rápidu hacia alantre o hacia atrás</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Bucle"</string>
+    <string name="single">"Simple"</string>
+    <string name="stereo">"Estereu"</string>
+    <string name="speaker_on">Altavoz encesu</string>
+    <string name="speaker_off">Altavoz apagáu</string>
+    <string name="speaker_need_headset">Coneuta unos auriculares pa usar esta carauterística.</string>
+    <string name="single_track">"Una pista"</string>
+    <string name="input_url">"Introducir URL"</string>
+    <string name="streaming_settings">"Axustes de fluxu de datos"</string>
+    <string name="next">"Siguiente"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamañu del buffer</string>
+    <string name="apn">APN preferida</string>
+    <string name="rtp_min_port">Puertu mínimu</string>
+    <string name="rtp_max_port">Puertu máximu</string>
+    <string name="set_rtp_min_port">Afitar el puertu min.</string>
+    <string name="set_rtp_max_port">Afitar el puertu máx.</string>
+    <string name="set_buffer_size">Afitar el tamañu del buffer</string>
+    <string name="set_apn">Seleicionar APN preferíu</string>
+    <string name="setting">Axustes</string>
+    <string name="server_timeout_title">"Escosó'l tiempu d'espera del sirvidor"</string>
+    <string name="server_timeout_message">"¿Reconeutar col sirvidor pa reproducir el videu?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Falló la conexón. Intentando volver a coneutar con %1$d\u2026"</string>
+    <string name="media_controller_live">En direutu</string>
+    <string name="media_controller_playing">Reproduciendo</string>
+    <string name="media_controller_connecting">Coneutando\u2026</string>
+    <string name="bookmark_add">"Amestar marcador"</string>
+    <string name="bookmark_display">"Amosar marcadores"</string>
+    <string name="bookmark_empty">"Ensin marcadores"</string>
+    <string name="bookmark_exist">"Esti marcador yá esiste"</string>
+    <string name="bookmark_add_success">"Marcador amestáu"</string>
+    <string name="bookmark_list">"Marcadores"</string>
+    <string name="bookmark_title">"Títulu"</string>
+    <string name="bookmark_location">"Allugamientu"</string>
+    <string name="delete_all">"Desanicialo too"</string>
+    <string name="default_title">"Títulu por defeutu"</string>
+    <string name="more_image">Más imáxenes</string>
+    <string name="mute_nosupport">Nun pue silenciase: videu non sofitáu</string>
+    <string name="map_activity_not_found_err">Nun hai nenguna aplicación de mapes instalada p\'amosar la llocalización.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d videu</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">La cantidá d\'elementos esbillaos pa compartir ye de 300</string>
+    <string name="share_dialogue_title">Compartir per</string>
+    <string name="no_faces">Ensin cares</string>
+    <string name="fail_trim">El videu nun pue retayase</string>
+    <string name="can_not_trim">Namái puen retayase los ficheros mp4 y 3gp</string>
+    <string name="drm_license_info">Información de llicencia de DRM</string>
+    <string name="timeline_title">Llinia temporal</string>
+    <string name="albums_title">Álbumes</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Vista de llistáu</string>
+    <string name="tvEmptyAlbum">Nun s\'alcontraron semeyes</string>
+    <string name="tvEmptyVideos">Nun s\'alcontraron vídeos</string>
+    <string name="text_makeup_whiten">Ablanquiao</string>
+    <string name="text_makeup_Soften">Suavizao</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Güeyos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Pizarra</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Desaniciar reflexos</string>
+    <string name="hazebuster_acts">Anti-nublina</string>
+    <string name="seestraight_acts">Ver direutamente</string>
+    <string name="seestraight_input_image_is_small">La imaxe d\'entrada ye perpequeña como pa procesase.</string>
+    <string name="seestraight_process_fail">Nun pudo procesase la imaxe.</string>
+    <string name="trim_video_exit_title">¿Escartar cambeos?</string>
+    <string name="trim_video_exit_msg">¿Escartar los cambeos fechos nesti videu?</string>
+    <string name="trim_video_exit_discard">ESCARTAR</string>
+</resources>
diff --git a/res/values-ast-rES/filtershow_strings.xml b/res/values-ast-rES/filtershow_strings.xml
new file mode 100644
index 0000000..170c036
--- /dev/null
+++ b/res/values-ast-rES/filtershow_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">Editor de semeyes</string>
+    <string name="cannot_load_image">Fallu al cargar la imaxe!</string>
+    <string name="cannot_edit_original">Nun pue editase l\'orixinal</string>
+    <string name="original_picture_text">@string/original</string>
+    <string name="setting_wallpaper">Afitando fondu de pantalla...</string>
+    <string name="download_failure">Nun pudo baxase la semeya. Rede non disponible.</string>
+    <string name="original">Orixinal</string>
+    <string name="custom_border">Personalizáu</string>
+    <string name="filtershow_undo">Desfacer</string>
+    <string name="filtershow_redo">Refacer</string>
+    <string name="show_imagestate_panel">Amosar efeutos aplicaos</string>
+    <string name="hide_imagestate_panel">Anubrir efeutos aplicaos</string>
+    <string name="export_image">Esportar</string>
+    <string name="print_image">Imprentar</string>
+    <string name="export_flattened">Esportar imaxe aplastada</string>
+    <string name="select_output_settings">La imaxe esportada va ser una copia y nun va incluyir l\'historial.</string>
+    <string name="quality">Calidá</string>
+    <string name="size">Tamañu</string>
+    <string name="x">x</string>
+    <string name="menu_settings">Axustes</string>
+    <string name="unsaved">Hai cambeos ensin guardar nesta imaxe.</string>
+    <string name="save_before_exit">¿Quies guardar enantes de salir?</string>
+    <string name="save_and_exit">Guardar y colar</string>
+    <string name="save_and_processing">Procesando imaxe con resolución completa...</string>
+    <string name="exit">Salir</string>
+    <string name="history">Historial</string>
+    <string name="reset">Reafitar</string>
+    <string name="history_original">@string/original</string>
+    <string name="imageState">Efeutos aplicaos</string>
+    <string name="compare_original">Comparar</string>
+    <string name="apply_effect">Aplicar</string>
+    <string name="reset_effect">Reafitar</string>
+    <string name="aspect">Aspeutu</string>
+    <string name="aspect1to1_effect">1:1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">Nengún</string>
+    <string name="aspectOriginal_effect">@string/original</string>
+    <string name="Fixed">Fixu</string>
+    <string name="tinyplanet">Pequeñu planeta</string>
+    <string name="exposure" msgid="1229093066434614811">Esposición</string>
+    <string name="sharpness">Nitidez</string>
+    <string name="contrast">Contraste</string>
+    <string name="vibrance">Intensidá</string>
+    <string name="saturation">Saturación</string>
+    <string name="bwfilter">Filtru b/n</string>
+    <string name="wbalance">Color automáticu</string>
+    <string name="hue">Tonalidá</string>
+    <string name="shadow_recovery">Solombres</string>
+    <string name="highlight_recovery">Destacáu</string>
+    <string name="curvesRGB">Curvar</string>
+    <string name="vignette">Viñeta</string>
+    <string name="vignette_main">Viñeta</string>
+    <string name="vignette_exposure">Esposición</string>
+    <string name="vignette_saturation">Saturación</string>
+    <string name="vignette_contrast">Contraste</string>
+    <string name="vignette_falloff">Atenuación</string>
+    <string name="redeye">Güeyos bermeyos</string>
+    <string name="imageDraw">Dibuxu</string>
+    <string name="straighten" msgid="5217801513491493491">Enderezar</string>
+    <string name="crop" msgid="5584000454518174632">Recortar</string>
+    <string name="rotate" msgid="460017689320955494">Xirar</string>
+    <string name="mirror">Espeyu</string>
+    <string name="negative">Negativu</string>
+    <string name="none" msgid="3601545724573307541">Nengún</string>
+    <string name="edge">Bordes</string>
+    <string name="kmeans">Posterizar</string>
+    <string name="downsample">Amenorgar calidá</string>
+    <string name="grad">Graduada</string>
+    <string name="editor_grad_brightness">Brilléu</string>
+    <string name="editor_grad_contrast">Contraste</string>
+    <string name="editor_grad_saturation">Saturación</string>
+    <string name="editor_chan_sat_main">Principal</string>
+    <string name="editor_chan_sat_red">Bermeyu</string>
+    <string name="editor_chan_sat_yellow">Mariellu</string>
+    <string name="editor_chan_sat_green">Verde</string>
+    <string name="editor_chan_sat_cyan">Cianu</string>
+    <string name="editor_chan_sat_blue">Azul</string>
+    <string name="editor_chan_sat_magenta">Maxenta</string>
+    <string name="editor_grad_style">Estilu</string>
+    <string name="editor_grad_new">Nueva</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">Bermeyu</string>
+    <string name="curves_channel_green">Verde</string>
+    <string name="curves_channel_blue">Azul</string>
+    <string name="draw_style">Estilu</string>
+    <string name="draw_size">Tamañu</string>
+    <string name="draw_hue">Matiz</string>
+    <string name="draw_saturation">Saturación</string>
+    <string name="draw_value">Brilléu</string>
+    <string name="draw_color">Color</string>
+    <string name="draw_style_line">Llinies</string>
+    <string name="draw_style_brush_spatter">Rotulador</string>
+    <string name="draw_style_brush_marker">Manches</string>
+    <string name="draw_clear">Llimpiar</string>
+    <string name="color_border_size">Grosor</string>
+    <string name="color_border_corner_size">Tamañu esquina</string>
+    <string name="color_border_color">Color</string>
+    <string name="color_border_clear">Llimpiar</string>
+    <string name="color_pick_select">Escoyer un color personalizáu</string>
+    <string name="color_pick_title">Seleicionar color</string>
+    <string name="draw_size_title">Seleicionar tamañu</string>
+    <string name="draw_size_accept">ACEUTAR</string>
+    <string name="state_panel_original">Orixinal</string>
+    <string name="state_panel_result">Resultáu</string>
+    <string name="filtershow_notification_label">Guardando imaxe</string>
+    <string name="filtershow_notification_message">Procesando...</string>
+    <string name="filtershow_save_preset">Guardar valor predetermináu</string>
+    <string name="filtershow_manage_preset">Alministrar predeterminaos</string>
+    <string name="filtershow_new_preset">Valor predetermináu nuevu</string>
+    <string name="filtershow_preset_name">Nome predetermináu</string>
+    <string name="filtershow_show_info_panel">Información</string>
+    <string name="filtershow_show_info_panel_name">Nome de la imaxe</string>
+    <string name="filtershow_show_info_panel_size">Tamañu de la imaxe</string>
+    <string name="filtershow_show_info_panel_histogram">Histograma</string>
+    <string name="filtershow_show_info_panel_exif">Datos de EXIF</string>
+    <string name="filtershow_add_button_looks">Predetermináu</string>
+    <string name="filtershow_add_button_versions">Versión</string>
+    <string name="filtershow_version_original">Orixinal</string>
+    <string name="filtershow_version_current">Actual</string>
+    <string name="filtershow_exif_model">Modelu</string>
+    <string name="filtershow_exif_aperture">Apertura</string>
+    <string name="filtershow_exif_focal_length">Llonxitú focal</string>
+    <string name="filtershow_exif_iso">ISO</string>
+    <string name="filtershow_exif_subject_distance">Distancia del suxetu</string>
+    <string name="filtershow_exif_date">Data de creación</string>
+    <string name="filtershow_exif_f_stop">Númberu f</string>
+    <string name="filtershow_exif_exposure_time">Tiempu d\'esposición</string>
+    <string name="filtershow_exif_copyright">Copyright</string>
+</resources>
diff --git a/res/values-ast-rES/strings.xml b/res/values-ast-rES/strings.xml
new file mode 100644
index 0000000..354f9b1
--- /dev/null
+++ b/res/values-ast-rES/strings.xml
@@ -0,0 +1,439 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Galería</string>
+    <string name="gadget_title">Marcu de semeya</string>
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="movie_view_label">Reproductor de videu</string>
+    <string name="loading_video">Cargando videu…</string>
+    <string name="loading_image">Cargando imaxe…</string>
+    <string name="loading_account">Cargando cuenta...</string>
+    <string name="resume_playing_title">Reanudar videu</string>
+    <string name="resume_playing_message">Reanudar reproducción a partir de %s ?</string>
+    <string name="resume_playing_resume">Reanudar reproducción</string>
+    <string name="loading">Loading\u2026</string>
+    <string name="fail_to_load">Fallu al cargar</string>
+    <string name="fail_to_load_image">Nun pue cargase la imaxe.</string>
+    <string name="no_thumbnail">Nun hai miniatures.</string>
+    <string name="resume_playing_restart">Volver a reproducir</string>
+    <string name="crop_save_text">ACEUTAR</string>
+    <string name="ok">ACEUTAR</string>
+    <string name="multiface_crop_help">Toca una cara pa entamar.</string>
+    <string name="saving_image">Guardando imaxe...</string>
+    <string name="filtershow_saving_image">Guardando imaxe en <xliff:g id="ALBUM_NAME">%1$s</xliff:g> …</string>
+    <string name="save_error">Fallu al guardar la imaxe recortada</string>
+    <string name="crop_label">Recortar</string>
+    <string name="trim_label">Recortar videu</string>
+    <string name="select_image">Esbillar semeya</string>
+    <string name="select_video">Esbillar videu</string>
+    <string name="select_item">Esbillar elementu</string>
+    <string name="select_album">Esbillar álbum</string>
+    <string name="select_group">Esbillar grupu</string>
+    <string name="set_image">Afitar como...</string>
+    <string name="set_wallpaper">Afitar fondu de pantalla</string>
+    <string name="wallpaper">Afitando fondu de pantalla...</string>
+    <string name="camera_setas_wallpaper">Fondu de pantalla</string>
+    <string name="delete">Desaniciar</string>
+    <plurals name="delete_selection">
+        <item quantity="one">¿Desaniciar elementu esbilláu?</item>
+        <item quantity="other">¿Desaniciar elementos esbillaos?</item>
+    </plurals>
+    <string name="confirm">Confirmar</string>
+    <string name="cancel">Encaboxar</string>
+    <string name="share">Compartir</string>
+    <string name="share_panorama">Compartir panorámica</string>
+    <string name="share_as_photo">Compartir como semeya</string>
+    <string name="deleted">Desaniciada</string>
+    <string name="undo">DESFACER</string>
+    <string name="select_all">Marcalo too</string>
+    <string name="deselect_all">Desmarcalo too</string>
+    <string name="slideshow">Presentación</string>
+    <string name="details">Detalles</string>
+    <string name="details_title">%1$d de %2$d elementos:</string>
+    <string name="close">Zarrar</string>
+    <string name="switch_to_camera">Cambiar a la cámara</string>
+    <plurals name="number_of_items_selected">
+        <item quantity="one">%1$d esbilláu</item>
+        <item quantity="other">%1$d esbillaos</item>
+    </plurals>
+    <plurals name="number_of_albums_selected">
+        <item quantity="one">%1$d esbilláu</item>
+        <item quantity="other">%1$d esbillaos</item>
+    </plurals>
+    <plurals name="number_of_groups_selected">
+        <item quantity="one">%1$d esbilláu</item>
+        <item quantity="other">%1$d esbillaos</item>
+    </plurals>
+    <string name="show_on_map">Amosar nel mapa</string>
+    <string name="rotate_left">Xirar a la esquierda</string>
+    <string name="rotate_right">Xirar a la derecha</string>
+    <string name="no_such_item">Nun pudo alcontrase l\'elementu.</string>
+    <string name="edit">Editar</string>
+    <string name="simple_edit">Edición simple</string>
+    <string name="process_caching_requests">Procesando solicitúes d\'almacenamientu en caché</string>
+    <string name="caching_label">Atroxando na caché\u2026</string>
+    <string name="crop_action">Recortar</string>
+    <string name="trim_action">Recortar</string>
+    <string name="mute_action">Silenciar</string>
+    <string name="set_as">Afitar como</string>
+    <string name="video_mute_err">Nun pue silenciase\'l videu.</string>
+    <string name="video_err">Nun pue reproducise\'l videu.</string>
+    <string name="group_by_location">Per llocalización</string>
+    <string name="group_by_time">Per data</string>
+    <string name="group_by_tags">Por etiquetes</string>
+    <string name="group_by_faces">Por persones</string>
+    <string name="group_by_album">Por álbum</string>
+    <string name="group_by_size">Por tamañu</string>
+    <string name="untagged">Ensin etiquetes</string>
+    <string name="no_location">Ensin allugamientu</string>
+    <string name="no_connectivity">Nun pudieron identificase dalgunes llocalizaciones por fallos na rede.</string>
+    <string name="sync_album_error">Nun pudieron descargase les semeyes del álbum. Inténtalo de nueves más tarde.</string>
+    <string name="show_images_only">Namái imáxenes</string>
+    <string name="show_videos_only">Namái vídeos</string>
+    <string name="show_all">Imáxenes y vídeos</string>
+    <string name="appwidget_title">Galería de semeyes</string>
+    <string name="appwidget_empty_text">Nun hai semeyes.</string>
+    <string name="crop_saved">        La imaxe retayada guardóse en <xliff:g id="folder_name">%s</xliff:g>.</string>
+    <string name="no_albums_alert">Nun hai álbumes disponibles.</string>
+    <string name="empty_album">Nun hai imáxenes nin vídeos disponibles.</string>
+    <string name="picasa_posts">Publicaciones</string>
+    <string name="make_available_offline">Disponible ensin conexón</string>
+    <string name="sync_picasa_albums">Anovar</string>
+    <string name="done">Fecho</string>
+    <string name="sequence_in_set">%1$d de %2$d elementos:</string>
+    <string name="title">Títulu</string>
+    <string name="description">Descripción</string>
+    <string name="time">Hora</string>
+    <string name="location">Allugamientu</string>
+    <string name="path">Camín</string>
+    <string name="width">Anchor</string>
+    <string name="height">Altor</string>
+    <string name="orientation">Orientación</string>
+    <string name="duration">Duración</string>
+    <string name="mimetype">Tipu de MIME</string>
+    <string name="file_size">Tamañu del ficheru</string>
+    <string name="maker">Creador</string>
+    <string name="model">Modelu</string>
+    <string name="flash">Flax</string>
+    <string name="aperture">Apertura</string>
+    <string name="focal_length">Llonxitú focal</string>
+    <string name="white_balance">Balance de blancos</string>
+    <string name="exposure_time">Tiempu esposición</string>
+    <string name="iso">ISO</string>
+    <string name="unit_mm">mm</string>
+    <string name="manual">Manual</string>
+    <string name="auto">Automáticu</string>
+    <string name="flash_on">Flax activáu</string>
+    <string name="flash_off">Ensin flax</string>
+    <string name="unknown">Desconozse</string>
+    <string name="ffx_original">Orixinal</string>
+    <string name="ffx_vintage">Vintage</string>
+    <string name="ffx_instant">Instantánea</string>
+    <string name="ffx_bleach">Decolorar</string>
+    <string name="ffx_blue_crush">Azul</string>
+    <string name="ffx_bw_contrast">Blancu y prietu</string>
+    <string name="ffx_punch">Punch</string>
+    <string name="ffx_x_process">Procesamientu X</string>
+    <string name="ffx_washout">Latte</string>
+    <string name="ffx_washout_color">Litho</string>
+    <plurals name="make_albums_available_offline">
+        <item quantity="one">Faciendo que l\'álbum pueda vese ensin conexón</item>
+        <item quantity="other">Faciendo que los álbumes puedan vese ensin conexón...</item>
+    </plurals>
+    <string name="try_to_set_local_album_available_offline">        Esti elementu ta atroxáu llocalmente y disponible y fuera llinia.</string>
+    <string name="set_label_all_albums">Tolos álbumes</string>
+    <string name="set_label_local_albums">Álbumes llocales</string>
+    <string name="set_label_mtp_devices">Preseos MTP</string>
+    <string name="set_label_picasa_albums">Álbumes de Picasa</string>
+    <string name="free_space_format"><xliff:g id="BYTES">%s</xliff:g> llibres</string>
+    <string name="size_below"><xliff:g id="SIZE">%1$s</xliff:g> o inferior</string>
+    <string name="size_above"><xliff:g id="SIZE">%1$s</xliff:g> o superior</string>
+    <string name="size_between">De <xliff:g id="MIN_SIZE">%1$s</xliff:g> a <xliff:g id="MAX_SIZE">%2$s</xliff:g></string>
+    <string name="Import">Importar</string>
+    <string name="import_complete">Importación completada</string>
+    <string name="import_fail">Fallu al importar</string>
+    <string name="camera_connected">Cámara coneutada</string>
+    <string name="camera_disconnected">Cámara desconeutada</string>
+    <string name="click_import">Toca equí pa facer la importación.</string>
+    <string name="widget_type_album">Esbillar un álbum</string>
+    <string name="widget_type_shuffle">Toles imáxenes al debalu</string>
+    <string name="widget_type_photo">Esbillar una imaxe</string>
+    <string name="widget_type">Esbillar imáxenes</string>
+    <string name="slideshow_dream_name">Presentación</string>
+    <string name="albums">Álbumes</string>
+    <string name="times">Data</string>
+    <string name="locations">Allugamientos</string>
+    <string name="people">Persones</string>
+    <string name="tags">Etiquetes</string>
+    <string name="group_by">Agrupar por</string>
+    <string name="settings">Axustes</string>
+    <string name="add_account">Amestar cuenta</string>
+    <string name="folder_camera">Cámara</string>
+    <string name="folder_download">Descargaes</string>
+    <string name="folder_edited_online_photos">Semeyes online editaes</string>
+    <string name="folder_imported">Importaes</string>
+    <string name="folder_screenshot">Captures de pantalla</string>
+    <string name="help">Ayuda</string>
+    <string name="no_external_storage_title">Ensin almacenamientu</string>
+    <string name="no_external_storage">Nun hai almacenamientu esternu disponible.</string>
+    <string name="switch_photo_filmstrip">Vista de tira de película</string>
+    <string name="switch_photo_grid">Vista de cuadrícula</string>
+    <string name="switch_photo_fullscreen">Pantalla completa</string>
+    <string name="trimming">Recortando...</string>
+    <string name="muting">Silenciando...</string>
+    <string name="please_wait">Espera...</string>
+    <string name="save_into">Guardando videu en <xliff:g id="ALBUM_NAME">%1$s</xliff:g>…</string>
+    <string name="trim_too_short">Nun se pue recortar: el videu de destín ye enforma curtiu.</string>
+    <string name="pano_progress_text">Creando panorámica...</string>
+    <string name="save" msgid="8140440041190264400">Guardar</string>
+    <string name="ingest_import">@string/Import</string>
+    <string name="ingest_import_complete">@string/import_complete</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">Analizando conteníu...</string>
+    <plurals name="ingest_number_of_items_scanned">
+        <item quantity="one">%1$d elementu analizáu</item>
+        <item quantity="other">%1$d elementos analizaos</item>
+    </plurals>
+    <plurals name="ingest_number_of_items_selected">
+        <item quantity="one">%1$d elementu esbilláu</item>
+        <item quantity="other">%1$d elementos esbillaos</item>
+    </plurals>
+    <string name="ingest_sorting" msgid="624687230903648118">Ordenando...</string>
+    <string name="ingest_scanning_done">Escanéu fechu</string>
+    <string name="ingest_importing">Importando...</string>
+    <string name="ingest_empty_device">Nun hai conteníu disponible pa importar nesti preséu.</string>
+    <string name="ingest_no_device">Nun hai preseos MTP coneutaos</string>
+    <string name="ingest_switch_photo_grid">@string/switch_photo_grid</string>
+    <string name="ingest_switch_photo_fullscreen">@string/switch_photo_fullscreen</string>
+    <string name="camera_error_title">Fallu de cámara</string>
+    <string name="cannot_connect_camera">Nun pue accedese a la cámara.</string>
+    <string name="camera_disabled">Desactivóse la cámara poles polítiques de seguranza.</string>
+    <string name="camera_label">Cámara</string>
+    <string name="wait">Por favor, espera...</string>
+    <string name="no_storage" product="nosdcard">Pa poder usar la cámara, activa l\'almacenamientu USB.</string>
+    <string name="no_storage" product="default">Pa poder usar la cámara, inxerta una tarxeta SD.</string>
+    <string name="preparing_sd" product="nosdcard">Tresnando almacenamientu USB…</string>
+    <string name="preparing_sd" product="default">Tresnando tarxeta SD…</string>
+    <string name="access_sd_fail" product="nosdcard">Nun pudo accedese al almacenamientu USB.</string>
+    <string name="access_sd_fail" product="default">Nun pudo accedese a la tarxeta SD.</string>
+    <string name="review_cancel">ENCABOXAR</string>
+    <string name="review_ok">FECHO</string>
+    <string name="time_lapse_title">Grabación a intervalos de tiempu</string>
+    <string name="pref_camera_id_title">Escoyer cámara</string>
+    <string name="pref_camera_id_entry_back">Trasera</string>
+    <string name="pref_camera_id_entry_front">Delantera</string>
+    <string name="pref_camera_recordlocation_title">Atroxar allugamientu</string>
+    <string name="pref_camera_location_label">ALLUGAMIENTU</string>
+    <string name="pref_camera_timer_title">Cuenta atrás</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="one">1 segundu</item>
+        <item quantity="other">%d segundos</item>
+    </plurals>
+    <string name="pref_camera_timer_sound_default">@string/setting_on_value</string>
+    <string name="pref_camera_timer_sound_title">Pitar na cuenta atrás</string>
+    <string name="setting_off">Desactiváu</string>
+    <string name="setting_on">Activáu</string>
+    <string name="pref_video_quality_title">Calidá de videu</string>
+    <string name="pref_video_quality_entry_high">Alta</string>
+    <string name="pref_video_quality_entry_low">Baxa</string>
+    <string name="pref_video_time_lapse_frame_interval_title">Intervalu de tiempu</string>
+    <string name="pref_camera_settings_category">Axustes de la cámara</string>
+    <string name="pref_camcorder_settings_category">Configuración de videocámara</string>
+    <string name="pref_camera_picturesize_title">Tamañu d\'imaxe</string>
+    <string name="pref_camera_picturesize_entry_13mp">13 MP</string>
+    <string name="pref_camera_picturesize_entry_8mp">8 MP</string>
+    <string name="pref_camera_picturesize_entry_5mp">5 MP</string>
+    <string name="pref_camera_picturesize_entry_4mp">4 MP</string>
+    <string name="pref_camera_picturesize_entry_3mp">3 MP</string>
+    <string name="pref_camera_picturesize_entry_2mp">2 MP</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">2 MP (16:9)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">1,3 MP</string>
+    <string name="pref_camera_picturesize_entry_1mp">1 MP</string>
+    <string name="pref_camera_picturesize_entry_vga">VGA</string>
+    <string name="pref_camera_picturesize_entry_qvga">QVGA</string>
+    <string name="pref_camera_focusmode_title">Mou d\'enfoque</string>
+    <string name="pref_camera_focusmode_entry_auto">Auto</string>
+    <string name="pref_camera_focusmode_entry_infinity">Infinitu</string>
+    <string name="pref_camera_focusmode_entry_macro">Macro</string>
+    <string name="pref_camera_focusmode_label_auto">AUTO</string>
+    <string name="pref_camera_focusmode_label_infinity">INFINITU</string>
+    <string name="pref_camera_focusmode_label_macro">MACRO</string>
+    <string name="pref_camera_flashmode_title">Mou flax</string>
+    <string name="pref_camera_flashmode_label">MOU FLAX</string>
+    <string name="pref_camera_flashmode_entry_auto">Auto</string>
+    <string name="pref_camera_flashmode_entry_on">Activáu</string>
+    <string name="pref_camera_flashmode_entry_off">Desactiváu</string>
+    <string name="pref_camera_flashmode_label_auto">FLAX AUTOMÁTICU</string>
+    <string name="pref_camera_flashmode_label_on">FLAX ACTIVÁU</string>
+    <string name="pref_camera_flashmode_label_off">FLAX DESACTIVÁU</string>
+    <string name="pref_camera_whitebalance_title">Balance de blancos</string>
+    <string name="pref_camera_whitebalance_label">BALANCE DE BLANCOS</string>
+    <string name="pref_camera_whitebalance_entry_auto">Auto</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">En caldia</string>
+    <string name="pref_camera_whitebalance_entry_daylight">Lluz natural</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">Fluorescente</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">Ñuble</string>
+    <string name="pref_camera_whitebalance_label_auto">AUTO</string>
+    <string name="pref_camera_whitebalance_label_incandescent">EN CALDIA</string>
+    <string name="pref_camera_whitebalance_label_daylight">LLUZ NATURAL</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">FLUORESCENTE</string>
+    <string name="pref_camera_whitebalance_label_cloudy">ÑUBLE</string>
+    <string name="pref_camera_scenemode_title">Mou d\'escena</string>
+    <string name="pref_camera_scenemode_entry_auto">Auto</string>
+    <string name="pref_camera_scenemode_entry_hdr">HDR</string>
+    <string name="pref_camera_scenemode_entry_action">Aición</string>
+    <string name="pref_camera_scenemode_entry_night">Nueche</string>
+    <string name="pref_camera_scenemode_entry_sunset">Aséu</string>
+    <string name="pref_camera_scenemode_entry_party">Folixa</string>
+    <string name="pref_camera_scenemode_label_auto">NENGÚN</string>
+    <string name="pref_camera_scenemode_label_action">AICIÓN</string>
+    <string name="pref_camera_scenemode_label_night">NUECHE</string>
+    <string name="pref_camera_scenemode_label_sunset">ASÉU</string>
+    <string name="pref_camera_scenemode_label_party">FOLIXA</string>
+    <string name="pref_camera_countdown_label">CUENTA ATRÁS</string>
+    <string name="pref_camera_countdown_label_off">TEMPORIZADOR DESACTIVÁU</string>
+    <string name="pref_camera_countdown_label_one">1 SEGUNDU</string>
+    <string name="pref_camera_countdown_label_three">3 SEGUNDOS</string>
+    <string name="pref_camera_countdown_label_ten">10 SEGUNDOS</string>
+    <string name="pref_camera_countdown_label_fifteen">15 SEGUNDOS</string>
+    <string name="not_selectable_in_scene_mode">Nun pue seleicionase nel mou d\'escena.</string>
+    <string name="pref_exposure_title">Esposición</string>
+    <string name="pref_exposure_label">ESPOSICIÓN</string>
+    <string name="pref_camera_hdr_default">@string/setting_off_value</string>
+    <string name="pref_camera_hdr_label">HDR</string>
+    <string name="pref_camera_id_label_back">CÁMARA FRONTAL</string>
+    <string name="pref_camera_id_label_front">CÁMARA TRASERA</string>
+    <string name="dialog_ok">ACEUTAR</string>
+    <string name="spaceIsLow_content" product="nosdcard">Ta escosando l\'espaciu del almacenamientu USB. Camuda l\'axustes de calidá o desanicia delles imáxenes u ficheros.</string>
+    <string name="spaceIsLow_content" product="default">Nun hai espaciu na tarxeta SD. Cambia la configuración de calidá o desanicia dalgunes imáxenes o otros ficheros.</string>
+    <string name="video_reach_size_limit">Algamóse la llende de tamañu.</string>
+    <string name="pano_too_fast_prompt">Mui rápidu</string>
+    <string name="pano_dialog_prepare_preview">Preparando mou panorámicu</string>
+    <string name="pano_dialog_panorama_failed">Fallu al guardar imaxe panorámica</string>
+    <string name="pano_dialog_title">Panorámicu</string>
+    <string name="pano_capture_indication">Capturando panorámica</string>
+    <string name="pano_dialog_waiting_previous">Esperando semeya panorámica anterior...</string>
+    <string name="pano_review_saving_indication_str">Guardando...</string>
+    <string name="pano_review_rendering">Creando panorámica...</string>
+    <string name="tap_to_focus">Toca pa enfocar</string>
+    <string name="pref_video_effect_title">Efeutos</string>
+    <string name="effect_none">Nengún</string>
+    <string name="effect_goofy_face_squeeze">Comprimir</string>
+    <string name="effect_goofy_face_big_eyes">Güeyos grandes</string>
+    <string name="effect_goofy_face_big_mouth">Boca grande</string>
+    <string name="effect_goofy_face_small_mouth">Boca pequeña</string>
+    <string name="effect_goofy_face_big_nose">Nariz grande</string>
+    <string name="effect_goofy_face_small_eyes">Güeyos pequeños</string>
+    <string name="effect_backdropper_space">Nel espaciu</string>
+    <string name="effect_backdropper_sunset">Atapecer</string>
+    <string name="effect_backdropper_gallery">El to videu</string>
+    <string name="bg_replacement_message">Desactiva\'l preséu.\nDexa d\'usalu unos minutos.</string>
+    <string name="video_snapshot_hint">Toca pa facer una semeya mientres grabes un videu.</string>
+    <string name="video_recording_started">Anicióse la grabación de videu.</string>
+    <string name="video_recording_stopped">La grabación de videu detúvose.</string>
+    <string name="disable_video_snapshot_hint">La instantánea de videu inhabilítase al activar efeutos especiales.</string>
+    <string name="clear_effects">Quitar efeutos</string>
+    <string name="effect_silly_faces">CARES GRACIOSES</string>
+    <string name="effect_background">FONDU</string>
+    <string name="accessibility_shutter_button">Botón del obturador</string>
+    <string name="accessibility_menu_button">Botón de menú</string>
+    <string name="accessibility_review_thumbnail">Semeya más recién</string>
+    <string name="accessibility_camera_picker">Opción de cámara trasera y delantera</string>
+    <string name="accessibility_mode_picker">Cámara, videu o mou panorámicu</string>
+    <string name="accessibility_second_level_indicators">Más controles de configuración</string>
+    <string name="accessibility_back_to_first_level">Zarrar controles de configuración</string>
+    <string name="accessibility_zoom_control">Control del zoom</string>
+    <string name="accessibility_decrement">Amenorgar %1$s</string>
+    <string name="accessibility_increment">Aumentar %1$s</string>
+    <string name="accessibility_check_box">Caxellu %1$s</string>
+    <string name="accessibility_switch_to_camera">Cambiar a la cámara</string>
+    <string name="accessibility_switch_to_video">Cambiar a videu</string>
+    <string name="accessibility_switch_to_panorama">Cambiar a mou panorámicu</string>
+    <string name="accessibility_switch_to_new_panorama">Cambiar a nueva panorámica</string>
+    <string name="accessibility_switch_to_refocus">Cambiar a reenfoque</string>
+    <string name="accessibility_review_cancel">Encaboxar</string>
+    <string name="accessibility_review_ok">Fecho</string>
+    <string name="accessibility_review_retake">Revisar repetición</string>
+    <string name="accessibility_play_video">Ver un videu</string>
+    <string name="accessibility_pause_video">Posar videu</string>
+    <string name="accessibility_reload_video">Volver a cargar videu</string>
+    <string name="accessibility_time_bar">Barra de tiempu del reproductor de videu</string>
+    <string name="capital_on">SÍ</string>
+    <string name="capital_off">NON</string>
+    <string name="pref_video_time_lapse_frame_interval_off">Desactiváu</string>
+    <string name="pref_video_time_lapse_frame_interval_500">0,5 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 segundu</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">1,5 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2,5 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 segundos</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">0,5 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">1 minutu</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">1,5 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2,5 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 minutos</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">0,5 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 hora</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">1,5 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2,5 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 hores</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 hores</string>
+    <string name="time_lapse_seconds">segundos</string>
+    <string name="time_lapse_minutes">minutos</string>
+    <string name="time_lapse_hours">hores</string>
+    <string name="time_lapse_interval_set">Fecho</string>
+    <string name="set_time_interval">Afita intervalu de tiempu</string>
+    <string name="set_time_interval_help">L\'intervalu de tiempu ta desactiváu. Activa esta función p\'afitar un intervalu.</string>
+    <string name="set_timer_help">El temporizador de cuenta atrás ta desactiváu. Activa esta opción pa ver la cuenta atrás enantes de facer una semeya.</string>
+    <string name="set_duration">Definir duración en segundos</string>
+    <string name="count_down_title_text">Cuenta atrás pa facer una semeya</string>
+    <string name="remember_location_title">¿Recordar allugamientu de semeyes?</string>
+    <string name="remember_location_prompt">Etiqueta les tos semeyes y vídeos coles llocalizaciones au se fexeron.\n\nOtres aplicaciones puen acceder a esta información, asina como a les imáxenes guardaes.</string>
+    <string name="remember_location_no">Non, gracies</string>
+    <string name="remember_location_yes">Sí</string>
+    <string name="menu_camera">Cámara</string>
+    <string name="menu_search">Guetar</string>
+    <string name="tab_photos">Semeyes</string>
+    <string name="tab_albums">Álbumes</string>
+    <string name="camera_menu_more_label">MÁS OPCIONES</string>
+    <string name="camera_menu_settings_label">AXUSTES</string>
+    <plurals name="number_of_photos">
+        <item quantity="one">%1$d semeya</item>
+        <item quantity="other">%1$d semeyes</item>
+    </plurals>
+</resources>
diff --git a/res/values-az/cm_strings.xml b/res/values-az/cm_strings.xml
new file mode 100644
index 0000000..0de70eb
--- /dev/null
+++ b/res/values-az/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Səsyazma vaxtı</string>
+</resources>
diff --git a/res/values-az/codeaurora_strings.xml b/res/values-az/codeaurora_strings.xml
new file mode 100644
index 0000000..70d8110
--- /dev/null
+++ b/res/values-az/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Addım</string>
+    <string name="step_option_desc">Sürətli irəli/geri çəkmə aralıqlarını özəlləşdir</string>
+    <string name="setp_option_three_second">3 saniyə</string>
+    <string name="setp_option_six_second">6 saniyə</string>
+    <string name="loop">"Dövr"</string>
+    <string name="single">"Tək"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Səsucaldan AÇIQ</string>
+    <string name="speaker_off">Səsucaldan QAPALI</string>
+    <string name="speaker_need_headset">Bu özəllikdən istifadə etmək üçün qulaqlıq taxın.</string>
+    <string name="single_track">"Tək parça"</string>
+    <string name="input_url">"URL daxil edin"</string>
+    <string name="streaming_settings">"Axın tənzimləmələri"</string>
+    <string name="next">"Sonrakı"</string>
+    <string name="previous">"Əvvəlki"</string>
+    <string name="buffer_size">Bufer ölçüsü</string>
+    <string name="apn">Üstünlük verilən APN</string>
+    <string name="rtp_min_port">Min. bağlantı nöqtəsi</string>
+    <string name="rtp_max_port">Maks. bağlantı nöqtəsi</string>
+    <string name="set_rtp_min_port">Min bağlantı nöqtəsini tənzimlə</string>
+    <string name="set_rtp_max_port">Max bağlantı nöqtəsini tənzimlə</string>
+    <string name="set_buffer_size">Bufer ölçüsünü tənzimlə</string>
+    <string name="set_apn">Üstünlük verilən APN\'i seçin</string>
+    <string name="setting">Tənzimləmələr</string>
+    <string name="server_timeout_title">"Serverin bitmə vaxtı"</string>
+    <string name="server_timeout_message">"Videonu oynatmaq üçün serverlə yenidən bağlantı qurulsun?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Bağlanma xətası, %1$d üçün yenidən bağlantı qurulur\u2026"</string>
+    <string name="media_controller_live">Canlı</string>
+    <string name="media_controller_playing">Oynadılır</string>
+    <string name="media_controller_connecting">Bağlantı qurulur\u2026</string>
+    <string name="bookmark_add">"Əlfəcin əlavə et"</string>
+    <string name="bookmark_display">"Əlfəcinləri göstər"</string>
+    <string name="bookmark_empty">"Əlfəcin yoxdur"</string>
+    <string name="bookmark_exist">"Əlfəcin artıq mövcuddur"</string>
+    <string name="bookmark_add_success">"Əlfəcin əlavə edildi"</string>
+    <string name="bookmark_list">"Əlfəcinlər"</string>
+    <string name="bookmark_title">"Başlıq"</string>
+    <string name="bookmark_location">"Yerləşmə"</string>
+    <string name="delete_all">"Hamısını sil"</string>
+    <string name="default_title">"Standart başlıq"</string>
+    <string name="more_image">Daha çox təsvir</string>
+    <string name="mute_nosupport">Səsi kəsilə bilmir : video dəstəklənmir</string>
+    <string name="map_activity_not_found_err">Yerləşməni göstərmək üçün quraşdırılmış xəritə tətbiqi yoxdur.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Paylaşmaq üçün maksimum 300 element seçilə bilər</string>
+    <string name="share_dialogue_title">Paylaş</string>
+    <string name="no_faces">Üz yoxdur</string>
+    <string name="fail_trim">Bağışlayın, bu video fayl kəsilə bilməz</string>
+    <string name="can_not_trim">Yalnız mp4 və 3gp faylları kəsilə bilər</string>
+    <string name="drm_license_info">DRM lisenziya məlumatı</string>
+    <string name="timeline_title">Zaman tuneli</string>
+    <string name="albums_title">Albomlar</string>
+    <string name="videos_title">Videolar</string>
+    <string name="action_viewtype_list">Siyahı görünüşü</string>
+    <string name="tvEmptyAlbum">Foto tapılmadı</string>
+    <string name="tvEmptyVideos">Video tapılmadı</string>
+    <string name="text_makeup_whiten">Ağart</string>
+    <string name="text_makeup_Soften">Yumşalt</string>
+    <string name="text_makeup_trimface">Üz kəsmə</string>
+    <string name="text_makeup_bigeye">Böyük göz</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Ağ lövhə</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Parıltını Çıxart</string>
+    <string name="hazebuster_acts">Duman Təmizləyici</string>
+    <string name="seestraight_acts">Düz Bax</string>
+    <string name="seestraight_input_image_is_small">Təsvir, emal edilə bilməyəcək qədər kiçikdir.</string>
+    <string name="seestraight_process_fail">Təsvir emal edilə bilmədi.</string>
+    <string name="trim_video_exit_title">Dəyişikliklər ləğv edilsin?</string>
+    <string name="trim_video_exit_msg">Bu videoda edilmiş dəyişikliklər ləğv edilsin?</string>
+    <string name="trim_video_exit_discard">LƏĞV ET</string>
+</resources>
diff --git a/res/values-b+sr+Latn/filtershow_strings.xml b/res/values-b+sr+Latn/filtershow_strings.xml
deleted file mode 100644
index da90f06..0000000
--- a/res/values-b+sr+Latn/filtershow_strings.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="title_activity_filter_show" msgid="2036539130684382763">"Uređivač slika"</string>
-    <string name="cannot_load_image" msgid="5023634941212959976">"Nije moguće učitati sliku!"</string>
-    <string name="cannot_edit_original" msgid="5890293845882609388">"Nije moguće izmeniti original"</string>
-    <!-- no translation found for original_picture_text (3076213290079909698) -->
-    <skip />
-    <string name="setting_wallpaper" msgid="4679087092300036632">"Podešavanje pozadine"</string>
-    <string name="download_failure" msgid="5923323939788582895">"Nije moguće preuzeti sliku. Mreža nije dostupna."</string>
-    <string name="original" msgid="3524493791230430897">"Originalna"</string>
-    <string name="borders" msgid="2067345080568684614">"Ivice"</string>
-    <string name="custom_border" msgid="8679893731790931871">"Prilagođeno"</string>
-    <string name="filtershow_undo" msgid="6781743189243585101">"Opozovi"</string>
-    <string name="filtershow_redo" msgid="4219489910543059747">"Ponovi"</string>
-    <string name="show_imagestate_panel" msgid="281932769701043015">"Prikaži primenjene efekte"</string>
-    <string name="hide_imagestate_panel" msgid="7207643485811695257">"Sakrij primenjene efekte"</string>
-    <string name="export_image" msgid="3202835713172222134">"Izvezi"</string>
-    <string name="print_image" msgid="1942989216591621413">"Štampaj"</string>
-    <string name="export_flattened" msgid="9046192331465915411">"Izvezi jednoslojnu sliku"</string>
-    <string name="select_output_settings" msgid="1268532018080310748">"Izvezena slika biće kopija bez istorije."</string>
-    <string name="quality" msgid="179292110309050529">"Kvalitet"</string>
-    <string name="size" msgid="4639404642236356037">"Veličina"</string>
-    <string name="x" msgid="6810256999024563662">"x"</string>
-    <string name="menu_settings" msgid="6428291655769260831">"Podešavanja"</string>
-    <string name="unsaved" msgid="8704442449002374375">"Postoje nesačuvane izmene ove slike."</string>
-    <string name="save_before_exit" msgid="2680660633675916712">"Želite li da sačuvate pre nego što izađete?"</string>
-    <string name="save_and_exit" msgid="3628425023766687419">"Sačuvaj i izađi"</string>
-    <string name="save_and_processing" msgid="6371565035837463194">"Obrađivanje slike u punoj rezoluciji..."</string>
-    <string name="exit" msgid="242642957038770113">"Izađi"</string>
-    <string name="history" msgid="455767361472692409">"Istorija"</string>
-    <string name="reset" msgid="9013181350779592937">"Resetuj"</string>
-    <!-- no translation found for history_original (150973253194312841) -->
-    <skip />
-    <string name="imageState" msgid="8632586742752891968">"Primenjeni efekti"</string>
-    <string name="compare_original" msgid="8140838959007796977">"Uporedi"</string>
-    <string name="apply_effect" msgid="1218288221200568947">"Primeni"</string>
-    <string name="reset_effect" msgid="7712605581024929564">"Resetuj"</string>
-    <string name="aspect" msgid="4025244950820813059">"Razmera"</string>
-    <string name="aspect1to1_effect" msgid="1159104543795779123">"1:1"</string>
-    <string name="aspect4to3_effect" msgid="7968067847241223578">"4:3"</string>
-    <string name="aspect3to4_effect" msgid="7078163990979248864">"3:4"</string>
-    <string name="aspect4to6_effect" msgid="1410129351686165654">"4:6"</string>
-    <string name="aspect5to7_effect" msgid="5122395569059384741">"5:7"</string>
-    <string name="aspect7to5_effect" msgid="5780001758108328143">"7:5"</string>
-    <string name="aspect9to16_effect" msgid="7740468012919660728">"16:9"</string>
-    <string name="aspectNone_effect" msgid="6263330561046574134">"Ništa"</string>
-    <!-- no translation found for aspectOriginal_effect (5678516555493036594) -->
-    <skip />
-    <string name="Fixed" msgid="8017376448916924565">"Fiksno"</string>
-    <string name="tinyplanet" msgid="2783694326474415761">"Mala planeta"</string>
-    <string name="exposure" msgid="6526397045949374905">"Ekspozicija"</string>
-    <string name="sharpness" msgid="6463103068318055412">"Oštrina"</string>
-    <string name="contrast" msgid="2310908487756769019">"Kontrast"</string>
-    <string name="vibrance" msgid="3326744578577835915">"Živost boja"</string>
-    <string name="saturation" msgid="7026791551032438585">"Zasićenje"</string>
-    <string name="bwfilter" msgid="8927492494576933793">"Crno-beli filter"</string>
-    <string name="wbalance" msgid="6346581563387083613">"Automatska boja"</string>
-    <string name="hue" msgid="6231252147971086030">"Nijansa"</string>
-    <string name="shadow_recovery" msgid="3928572915300287152">"Senke"</string>
-    <string name="highlight_recovery" msgid="8262208470735204243">"Isticanja"</string>
-    <string name="curvesRGB" msgid="915010781090477550">"Krive"</string>
-    <string name="vignette" msgid="934721068851885390">"Vinjeta"</string>
-    <string name="vignette_main" msgid="6046495605390665423">"Vinjeta"</string>
-    <string name="vignette_exposure" msgid="6862058227309534094">"Ekspozicija"</string>
-    <string name="vignette_saturation" msgid="1617055207565719771">"Zasićenost boja"</string>
-    <string name="vignette_contrast" msgid="955732121756799897">"Kontrast"</string>
-    <string name="vignette_falloff" msgid="690918055030064199">"Slab. svetlosti"</string>
-    <string name="redeye" msgid="4508883127049472069">"Crvene oči"</string>
-    <string name="imageDraw" msgid="6918552177844486656">"Crtanje"</string>
-    <string name="straighten" msgid="26025591664983528">"Ispravljanje"</string>
-    <string name="crop" msgid="5781263790107850771">"Opsecanje"</string>
-    <string name="rotate" msgid="2796802553793795371">"Rotiraj"</string>
-    <string name="mirror" msgid="5482518108154883096">"Ogledalo"</string>
-    <string name="negative" msgid="6998313764388022201">"Negativ"</string>
-    <string name="none" msgid="6633966646410296520">"Ništa"</string>
-    <string name="edge" msgid="7036064886242147551">"Ivice"</string>
-    <string name="kmeans" msgid="2080952022674981541">"Posterizuj"</string>
-    <string name="downsample" msgid="3552938534146980104">"Smanji"</string>
-    <string name="grad" msgid="546774853424848655">"Gradacija"</string>
-    <string name="editor_grad_brightness" msgid="5937316734380235741">"Osvetljenost"</string>
-    <string name="editor_grad_contrast" msgid="3454456673401803360">"Kontrast"</string>
-    <string name="editor_grad_saturation" msgid="3760247354109521726">"Zasićenost boja"</string>
-    <string name="editor_chan_sat_main" msgid="4427652337797121940">"Glavno"</string>
-    <string name="editor_chan_sat_red" msgid="1699222266490540696">"Crvena"</string>
-    <string name="editor_chan_sat_yellow" msgid="1488997071882154179">"Žuta"</string>
-    <string name="editor_chan_sat_green" msgid="1514055896212975167">"Zelena"</string>
-    <string name="editor_chan_sat_cyan" msgid="1367634650172508288">"Cijan"</string>
-    <string name="editor_chan_sat_blue" msgid="384409736863387895">"Plava"</string>
-    <string name="editor_chan_sat_magenta" msgid="6689215719351415546">"Magenta"</string>
-    <string name="editor_grad_style" msgid="2168414479007745179">"Stil"</string>
-    <string name="editor_grad_new" msgid="4857265951369377379">"novo"</string>
-    <string name="curves_channel_rgb" msgid="7909209509638333690">"RGB"</string>
-    <string name="curves_channel_red" msgid="4199710104162111357">"Crvena"</string>
-    <string name="curves_channel_green" msgid="3733003466905031016">"Zelena"</string>
-    <string name="curves_channel_blue" msgid="9129211507395079371">"Plava"</string>
-    <string name="draw_style" msgid="2036125061987325389">"Stil"</string>
-    <string name="draw_size" msgid="4360005386104151209">"Veličina"</string>
-    <string name="draw_hue" msgid="4975135843189267133">"Nijansa"</string>
-    <string name="draw_saturation" msgid="5394395648014454882">"Zasićen. boja"</string>
-    <string name="draw_value" msgid="6571604055161538273">"Osvetljenost"</string>
-    <string name="draw_color" msgid="2119030386987211193">"Boja"</string>
-    <string name="draw_style_line" msgid="9216476853904429628">"Linije"</string>
-    <string name="draw_style_brush_spatter" msgid="7612691122932981554">"Označivač"</string>
-    <string name="draw_style_brush_marker" msgid="8468302322165644292">"Prskanje"</string>
-    <string name="draw_clear" msgid="6728155515454921052">"Obriši"</string>
-    <string name="color_border_size" msgid="1086895807615869290">"Debljina"</string>
-    <string name="color_border_corner_size" msgid="7637235159438869979">"Veličina ugla"</string>
-    <string name="color_border_color" msgid="8765458414425980711">"Boja"</string>
-    <string name="color_border_clear" msgid="4418261191091091722">"Obriši"</string>
-    <string name="color_pick_select" msgid="734312818059057394">"Izaberi prilagođenu boju"</string>
-    <string name="color_pick_title" msgid="6195567431995308876">"Izbor boje"</string>
-    <string name="draw_size_title" msgid="3121649039610273977">"Izbor veličine"</string>
-    <string name="draw_size_accept" msgid="6781529716526190028">"Potvrdi"</string>
-    <string name="state_panel_original" msgid="9069584409934164419">"Originalna"</string>
-    <string name="state_panel_result" msgid="318640531123298676">"Rezultat"</string>
-    <string name="filtershow_notification_label" msgid="1653168445525855247">"Čuvanje slike"</string>
-    <string name="filtershow_notification_message" msgid="2661871765484036286">"Obrađuje se..."</string>
-    <string name="filtershow_save_preset" msgid="3933550455577927439">"Sačuvaj aktuelna podešavanja"</string>
-    <string name="filtershow_manage_preset" msgid="3872896753708921286">"Upravljaj korisničkim podeš."</string>
-    <string name="filtershow_new_preset" msgid="8923930134923416617">"Novo unapred određeno podešav."</string>
-    <string name="filtershow_preset_name" msgid="7015939727047649866">"Naziv unapred odr. podešavanja"</string>
-    <string name="filtershow_show_info_panel" msgid="5773036746043711115">"Informacije"</string>
-    <string name="filtershow_show_info_panel_name" msgid="5908258517140549439">"Naziv slike"</string>
-    <string name="filtershow_show_info_panel_size" msgid="1714666849204493017">"Veličina slike"</string>
-    <string name="filtershow_show_info_panel_histogram" msgid="2669188469897955809">"Histogram"</string>
-    <string name="filtershow_show_info_panel_exif" msgid="4965486882625125154">"EXIF podaci"</string>
-    <string name="filtershow_add_button_looks" msgid="8630823661416925426">"Unapred podešeno"</string>
-    <string name="filtershow_add_button_versions" msgid="7620107266685809612">"Verzija"</string>
-    <string name="filtershow_version_original" msgid="1413894292200912828">"Original"</string>
-    <string name="filtershow_version_current" msgid="6609334422797468952">"Aktuelno"</string>
-    <string name="filtershow_exif_model" msgid="3543206476046267466">"Model"</string>
-    <string name="filtershow_exif_aperture" msgid="5076571522763604380">"Otvor blende"</string>
-    <string name="filtershow_exif_focal_length" msgid="5925151469731623706">"Žižna daljina"</string>
-    <string name="filtershow_exif_iso" msgid="5822494416955625317">"ISO"</string>
-    <string name="filtershow_exif_subject_distance" msgid="4920632253433906646">"Udaljenost subjekta"</string>
-    <string name="filtershow_exif_date" msgid="8882402253732028544">"Datum snimanja"</string>
-    <string name="filtershow_exif_f_stop" msgid="6081797865604483139">"Žižni broj"</string>
-    <string name="filtershow_exif_exposure_time" msgid="4099067062781294115">"Vreme ekspozicije"</string>
-    <string name="filtershow_exif_copyright" msgid="8801875918803737581">"Autorska prava"</string>
-</resources>
diff --git a/res/values-be/cm_strings.xml b/res/values-be/cm_strings.xml
new file mode 100644
index 0000000..fc34095
--- /dev/null
+++ b/res/values-be/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Час запісу</string>
+</resources>
diff --git a/res/values-be/codeaurora_strings.xml b/res/values-be/codeaurora_strings.xml
new file mode 100644
index 0000000..00dc305
--- /dev/null
+++ b/res/values-be/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Крок перамоткі</string>
+    <string name="step_option_desc">Налада інтэрвалу для хуткага прагляду наперад ці назад</string>
+    <string name="setp_option_three_second">3 секунды</string>
+    <string name="setp_option_six_second">6 секундаў</string>
+    <string name="loop">"Паўтор"</string>
+    <string name="single">"Аднаразова"</string>
+    <string name="stereo">"Стэрэа"</string>
+    <string name="speaker_on">УКЛ. дынамік</string>
+    <string name="speaker_off">ВЫКЛ. дынамік</string>
+    <string name="speaker_need_headset">Далучыце вушоўкі для выкарыстання гэтай функцыі.</string>
+    <string name="single_track">"Адна дарожка"</string>
+    <string name="input_url">"Увядзіце URL"</string>
+    <string name="streaming_settings">"\"Струменевая перадача"</string>
+    <string name="next">"Наступны трэк"</string>
+    <string name="previous">"Папярэдні трэк"</string>
+    <string name="buffer_size">Памер буфера</string>
+    <string name="apn">Кропка доступу па змаўчанні</string>
+    <string name="rtp_min_port">Мінімальны порт</string>
+    <string name="rtp_max_port">Максімальны порт</string>
+    <string name="set_rtp_min_port">Усталёўка мінімальнага нумара порта</string>
+    <string name="set_rtp_max_port">Усталёўка максімальнага нумара порта</string>
+    <string name="set_buffer_size">Усталёўка памеру буфера перадачы</string>
+    <string name="set_apn">Пераважная кропка доступу</string>
+    <string name="setting">Налады</string>
+    <string name="server_timeout_title">"Тайм-аўт сервера"</string>
+    <string name="server_timeout_message">"Перападключыцца да сервера для прайгравання відэафайла?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Збой сувязі. Паўторнае падлучэнне да %1$d\u2026"</string>
+    <string name="media_controller_live">Просты эфір</string>
+    <string name="media_controller_playing">Прайграванне</string>
+    <string name="media_controller_connecting">Падлучэнне\u2026</string>
+    <string name="bookmark_add">"Дадаць закладку"</string>
+    <string name="bookmark_display">"Паказаць закладкі"</string>
+    <string name="bookmark_empty">"Няма закладак"</string>
+    <string name="bookmark_exist">"Закладка ўжо існуе"</string>
+    <string name="bookmark_add_success">"Закладка дададзена"</string>
+    <string name="bookmark_list">"Закладкі"</string>
+    <string name="bookmark_title">"Назва"</string>
+    <string name="bookmark_location">"Месцазнаходжанне"</string>
+    <string name="delete_all">"Выдаліць усё"</string>
+    <string name="default_title">"Загаловак па змаўчанні"</string>
+    <string name="more_image">Іншыя выявы</string>
+    <string name="mute_nosupport">Немагчыма адключыць гук: відэафайл не падтрымваецца</string>
+    <string name="map_activity_not_found_err">Дадатак для працы з картамі не ўсталяваны. Паказ месцазнаходжання немагчымы.</string>
+    <string name="fail_trim">Дадзены відэафайл не можа быць абрэзаны</string>
+    <string name="drm_license_info">Звесткі пра ліцэнзію DRM</string>
+</resources>
diff --git a/res/values-be/filtershow_strings.xml b/res/values-be/filtershow_strings.xml
deleted file mode 100644
index 182bce1..0000000
--- a/res/values-be/filtershow_strings.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="title_activity_filter_show" msgid="2036539130684382763">"Фотарэдактар"</string>
-    <string name="cannot_load_image" msgid="5023634941212959976">"Не атрымлiваецца загрузіць малюнак"</string>
-    <string name="cannot_edit_original" msgid="5890293845882609388">"Немагчыма адрэдагаваць арыгінал"</string>
-    <!-- no translation found for original_picture_text (3076213290079909698) -->
-    <skip />
-    <string name="setting_wallpaper" msgid="4679087092300036632">"Усталёўка шпалер..."</string>
-    <string name="download_failure" msgid="5923323939788582895">"Не атрымалася спампаваць фота. Сетка недаступная."</string>
-    <string name="original" msgid="3524493791230430897">"Арыгiнал"</string>
-    <string name="borders" msgid="2067345080568684614">"Межы"</string>
-    <string name="custom_border" msgid="8679893731790931871">"Карыстальніцкі"</string>
-    <string name="filtershow_undo" msgid="6781743189243585101">"Адрабіць"</string>
-    <string name="filtershow_redo" msgid="4219489910543059747">"Паўтарыць"</string>
-    <string name="show_imagestate_panel" msgid="281932769701043015">"Паказваць прымененыя эфекты"</string>
-    <string name="hide_imagestate_panel" msgid="7207643485811695257">"Хаваць прымененыя эфекты"</string>
-    <string name="export_image" msgid="3202835713172222134">"Экспартаваць"</string>
-    <string name="print_image" msgid="1942989216591621413">"Друк"</string>
-    <string name="export_flattened" msgid="9046192331465915411">"Экспарт. зведзены відарыс"</string>
-    <string name="select_output_settings" msgid="1268532018080310748">"Экспартаваны відарыс будзе з\'яўляцца копіяй і не мець гісторыі."</string>
-    <string name="quality" msgid="179292110309050529">"Якасць"</string>
-    <string name="size" msgid="4639404642236356037">"Памер"</string>
-    <string name="x" msgid="6810256999024563662">"x"</string>
-    <string name="menu_settings" msgid="6428291655769260831">"Налады"</string>
-    <string name="unsaved" msgid="8704442449002374375">"Існуюць незахаваныя змяненні ў гэтай выяве."</string>
-    <string name="save_before_exit" msgid="2680660633675916712">"Жадаеце захавацца перад выхадам?"</string>
-    <string name="save_and_exit" msgid="3628425023766687419">"Захаваць і выйсці"</string>
-    <string name="save_and_processing" msgid="6371565035837463194">"Апрацоўка відарыса ў поўнай раздзяляльнасці..."</string>
-    <string name="exit" msgid="242642957038770113">"Выйсці"</string>
-    <string name="history" msgid="455767361472692409">"Гісторыя"</string>
-    <string name="reset" msgid="9013181350779592937">"Скінуць"</string>
-    <!-- no translation found for history_original (150973253194312841) -->
-    <skip />
-    <string name="imageState" msgid="8632586742752891968">"Прымененыя эфекты"</string>
-    <string name="compare_original" msgid="8140838959007796977">"Параўнаць"</string>
-    <string name="apply_effect" msgid="1218288221200568947">"Паспрабаваць"</string>
-    <string name="reset_effect" msgid="7712605581024929564">"Скінуць"</string>
-    <string name="aspect" msgid="4025244950820813059">"Аспект"</string>
-    <string name="aspect1to1_effect" msgid="1159104543795779123">"1:1"</string>
-    <string name="aspect4to3_effect" msgid="7968067847241223578">"4:3"</string>
-    <string name="aspect3to4_effect" msgid="7078163990979248864">"3:4"</string>
-    <string name="aspect4to6_effect" msgid="1410129351686165654">"4:6"</string>
-    <string name="aspect5to7_effect" msgid="5122395569059384741">"5:7"</string>
-    <string name="aspect7to5_effect" msgid="5780001758108328143">"7:5"</string>
-    <string name="aspect9to16_effect" msgid="7740468012919660728">"16:9"</string>
-    <string name="aspectNone_effect" msgid="6263330561046574134">"Няма"</string>
-    <!-- no translation found for aspectOriginal_effect (5678516555493036594) -->
-    <skip />
-    <string name="Fixed" msgid="8017376448916924565">"Выпраўленыя"</string>
-    <string name="tinyplanet" msgid="2783694326474415761">"Маленькая планета"</string>
-    <string name="exposure" msgid="6526397045949374905">"Экспазіцыя"</string>
-    <string name="sharpness" msgid="6463103068318055412">"Выразнасць"</string>
-    <string name="contrast" msgid="2310908487756769019">"Кантраст"</string>
-    <string name="vibrance" msgid="3326744578577835915">"Вібрацыя"</string>
-    <string name="saturation" msgid="7026791551032438585">"Насычанасць"</string>
-    <string name="bwfilter" msgid="8927492494576933793">"Чорна-белы фiльтр"</string>
-    <string name="wbalance" msgid="6346581563387083613">"Aўтаколер"</string>
-    <string name="hue" msgid="6231252147971086030">"Тон"</string>
-    <string name="shadow_recovery" msgid="3928572915300287152">"Цені"</string>
-    <string name="highlight_recovery" msgid="8262208470735204243">"Блікі"</string>
-    <string name="curvesRGB" msgid="915010781090477550">"Пэндзаль"</string>
-    <string name="vignette" msgid="934721068851885390">"Віньетка"</string>
-    <string name="vignette_main" msgid="6046495605390665423">"Віньетка"</string>
-    <string name="vignette_exposure" msgid="6862058227309534094">"Экспазіцыя"</string>
-    <string name="vignette_saturation" msgid="1617055207565719771">"Насычанасць"</string>
-    <string name="vignette_contrast" msgid="955732121756799897">"Кантраст"</string>
-    <string name="vignette_falloff" msgid="690918055030064199">"Віньетаванне"</string>
-    <string name="redeye" msgid="4508883127049472069">"Чырвонае вока"</string>
-    <string name="imageDraw" msgid="6918552177844486656">"Намаляваць"</string>
-    <string name="straighten" msgid="26025591664983528">"Выраўнаваць"</string>
-    <string name="crop" msgid="5781263790107850771">"Абрэзаць"</string>
-    <string name="rotate" msgid="2796802553793795371">"Павярнуць"</string>
-    <string name="mirror" msgid="5482518108154883096">"Люстра"</string>
-    <string name="negative" msgid="6998313764388022201">"Негатыў"</string>
-    <string name="none" msgid="6633966646410296520">"Няма"</string>
-    <string name="edge" msgid="7036064886242147551">"Краi"</string>
-    <string name="kmeans" msgid="2080952022674981541">"Плакат"</string>
-    <string name="downsample" msgid="3552938534146980104">"Паменшыць"</string>
-    <string name="grad" msgid="546774853424848655">"Градыентны"</string>
-    <string name="editor_grad_brightness" msgid="5937316734380235741">"Яркасць"</string>
-    <string name="editor_grad_contrast" msgid="3454456673401803360">"Кантраст"</string>
-    <string name="editor_grad_saturation" msgid="3760247354109521726">"Насычанасць"</string>
-    <string name="editor_chan_sat_main" msgid="4427652337797121940">"Галоўны"</string>
-    <string name="editor_chan_sat_red" msgid="1699222266490540696">"Чырвоны"</string>
-    <string name="editor_chan_sat_yellow" msgid="1488997071882154179">"Жоўты"</string>
-    <string name="editor_chan_sat_green" msgid="1514055896212975167">"Зялёны"</string>
-    <string name="editor_chan_sat_cyan" msgid="1367634650172508288">"Блакітны"</string>
-    <string name="editor_chan_sat_blue" msgid="384409736863387895">"Сiнi"</string>
-    <string name="editor_chan_sat_magenta" msgid="6689215719351415546">"Пурпурны"</string>
-    <string name="editor_grad_style" msgid="2168414479007745179">"Стыль"</string>
-    <string name="editor_grad_new" msgid="4857265951369377379">"новы"</string>
-    <string name="curves_channel_rgb" msgid="7909209509638333690">"RGB"</string>
-    <string name="curves_channel_red" msgid="4199710104162111357">"Чырвоны"</string>
-    <string name="curves_channel_green" msgid="3733003466905031016">"Зялёны"</string>
-    <string name="curves_channel_blue" msgid="9129211507395079371">"Сiнi"</string>
-    <string name="draw_style" msgid="2036125061987325389">"Стыль"</string>
-    <string name="draw_size" msgid="4360005386104151209">"Памер"</string>
-    <string name="draw_hue" msgid="4975135843189267133">"Адценне"</string>
-    <string name="draw_saturation" msgid="5394395648014454882">"Насычанасць"</string>
-    <string name="draw_value" msgid="6571604055161538273">"Яркасць"</string>
-    <string name="draw_color" msgid="2119030386987211193">"Колер"</string>
-    <string name="draw_style_line" msgid="9216476853904429628">"Лiнii"</string>
-    <string name="draw_style_brush_spatter" msgid="7612691122932981554">"Маркёр"</string>
-    <string name="draw_style_brush_marker" msgid="8468302322165644292">"Пырскi"</string>
-    <string name="draw_clear" msgid="6728155515454921052">"Ачысціць"</string>
-    <string name="color_border_size" msgid="1086895807615869290">"Таўшчыня"</string>
-    <string name="color_border_corner_size" msgid="7637235159438869979">"Памер вугла"</string>
-    <string name="color_border_color" msgid="8765458414425980711">"Колер"</string>
-    <string name="color_border_clear" msgid="4418261191091091722">"Ачысціць"</string>
-    <string name="color_pick_select" msgid="734312818059057394">"Выбраць іншы колер"</string>
-    <string name="color_pick_title" msgid="6195567431995308876">"Выберыце колер"</string>
-    <string name="draw_size_title" msgid="3121649039610273977">"Выберыце памер"</string>
-    <string name="draw_size_accept" msgid="6781529716526190028">"OK"</string>
-    <string name="state_panel_original" msgid="9069584409934164419">"Арыгiнал"</string>
-    <string name="state_panel_result" msgid="318640531123298676">"Вынiк"</string>
-    <string name="filtershow_notification_label" msgid="1653168445525855247">"Захаванне відарыса"</string>
-    <string name="filtershow_notification_message" msgid="2661871765484036286">"Апрацоўка..."</string>
-    <string name="filtershow_save_preset" msgid="3933550455577927439">"Захаваць бягучую загатоўку"</string>
-    <string name="filtershow_manage_preset" msgid="3872896753708921286">"Кіраванне карыстальніцкімі загатоўкамі"</string>
-    <string name="filtershow_new_preset" msgid="8923930134923416617">"Новая загатоўка"</string>
-    <string name="filtershow_preset_name" msgid="7015939727047649866">"Назва загатоўкі"</string>
-    <string name="filtershow_show_info_panel" msgid="5773036746043711115">"Інфармацыя"</string>
-    <string name="filtershow_show_info_panel_name" msgid="5908258517140549439">"Назва відарыса"</string>
-    <string name="filtershow_show_info_panel_size" msgid="1714666849204493017">"Памер відарыса"</string>
-    <string name="filtershow_show_info_panel_histogram" msgid="2669188469897955809">"Гістаграма"</string>
-    <string name="filtershow_show_info_panel_exif" msgid="4965486882625125154">"Даныя EXIF"</string>
-    <string name="filtershow_add_button_looks" msgid="8630823661416925426">"Загатоўка"</string>
-    <string name="filtershow_add_button_versions" msgid="7620107266685809612">"Версія"</string>
-    <string name="filtershow_version_original" msgid="1413894292200912828">"Арыгiнальная"</string>
-    <string name="filtershow_version_current" msgid="6609334422797468952">"Бягучая"</string>
-    <string name="filtershow_exif_model" msgid="3543206476046267466">"Мадэль"</string>
-    <string name="filtershow_exif_aperture" msgid="5076571522763604380">"Апертура"</string>
-    <string name="filtershow_exif_focal_length" msgid="5925151469731623706">"Фокусная адлегласць"</string>
-    <string name="filtershow_exif_iso" msgid="5822494416955625317">"ISO"</string>
-    <string name="filtershow_exif_subject_distance" msgid="4920632253433906646">"Адлегласць да аб\'екта"</string>
-    <string name="filtershow_exif_date" msgid="8882402253732028544">"Дата здымка"</string>
-    <string name="filtershow_exif_f_stop" msgid="6081797865604483139">"Лік дыяфрагмы"</string>
-    <string name="filtershow_exif_exposure_time" msgid="4099067062781294115">"Час экспазіцыі"</string>
-    <string name="filtershow_exif_copyright" msgid="8801875918803737581">"Аўтарскія правы"</string>
-</resources>
diff --git a/res/values-bg/cm_strings.xml b/res/values-bg/cm_strings.xml
new file mode 100644
index 0000000..226f5b3
--- /dev/null
+++ b/res/values-bg/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Време на запис</string>
+</resources>
diff --git a/res/values-bg/codeaurora_strings.xml b/res/values-bg/codeaurora_strings.xml
new file mode 100644
index 0000000..80c9a23
--- /dev/null
+++ b/res/values-bg/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Стъпка</string>
+    <string name="step_option_desc">Бърза настройка стъпка напред или назад</string>
+    <string name="setp_option_three_second">3 секунди</string>
+    <string name="setp_option_six_second">6 секунди</string>
+    <string name="loop">"Контур"</string>
+    <string name="single">"Единично"</string>
+    <string name="stereo">"Стерео"</string>
+    <string name="speaker_on">Високоговорител включен</string>
+    <string name="speaker_off">Високоговорител изключен</string>
+    <string name="speaker_need_headset">Включете слушалките, за да използвате тази функция.</string>
+    <string name="single_track">"Една песен"</string>
+    <string name="input_url">"Въведете URL адрес"</string>
+    <string name="streaming_settings">"Поточни настройки"</string>
+    <string name="next">"Следваща"</string>
+    <string name="previous">"Предишна"</string>
+    <string name="buffer_size">Размер на буфера</string>
+    <string name="apn">Предпочитан APN</string>
+    <string name="rtp_min_port">Минимален порт</string>
+    <string name="rtp_max_port">Максимален порт</string>
+    <string name="set_rtp_min_port">Задаване минимален порт</string>
+    <string name="set_rtp_max_port">Задаване максимален порт</string>
+    <string name="set_buffer_size">Задаване размер на буфера</string>
+    <string name="set_apn">Изберете предпочитана точка за достъп</string>
+    <string name="setting">Настройки</string>
+    <string name="server_timeout_title">"Време за изчакване на сървъра"</string>
+    <string name="server_timeout_message">"Да се свържа ли повторно със сървъра, за да изпълни видеото?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Неуспешна връзка, опитайте да се свържете с %1$d\u2026"</string>
+    <string name="media_controller_live">На живо</string>
+    <string name="media_controller_playing">Възпроизвеждане на</string>
+    <string name="media_controller_connecting">Свързване\u2026</string>
+    <string name="bookmark_add">"Добавяне на показалец"</string>
+    <string name="bookmark_display">"Показване на показалци"</string>
+    <string name="bookmark_empty">"Няма показалци"</string>
+    <string name="bookmark_exist">"Вече съществува показалец"</string>
+    <string name="bookmark_add_success">"Показалеца е добавен"</string>
+    <string name="bookmark_list">"Показалец"</string>
+    <string name="bookmark_title">"Заглавие"</string>
+    <string name="bookmark_location">"Местоположение"</string>
+    <string name="delete_all">"Изтрий всички"</string>
+    <string name="default_title">"Заглавие по подразбиране"</string>
+    <string name="more_image">Още снимки</string>
+    <string name="mute_nosupport">Не може да изключите звука: видеото не се поддържа</string>
+    <string name="map_activity_not_found_err">Няма инсталирано приложение което да покаже местоположението.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d видеоклип</item>
+        <item quantity="other">%1$d видеоклипа</item>
+    </plurals>
+    <string name="cannot_share_items">Максималният брой избрани елементи за сподеряне е 300</string>
+    <string name="share_dialogue_title">Споделяне чрез</string>
+    <string name="no_faces">Няма лица</string>
+    <string name="fail_trim">За съжаление, този видео файл не може да бъде орязан</string>
+    <string name="can_not_trim">Само mp4 и 3gp файлове могат да се режат</string>
+    <string name="drm_license_info">DRM лицензна информация</string>
+    <string name="timeline_title">Таймлайн</string>
+    <string name="albums_title">Албуми</string>
+    <string name="videos_title">Видео</string>
+    <string name="action_viewtype_list">Списъчен изглед</string>
+    <string name="tvEmptyAlbum">Не са намерени снимки</string>
+    <string name="tvEmptyVideos">Не са намерени видеоклипове</string>
+    <string name="text_makeup_whiten">Избелване</string>
+    <string name="text_makeup_Soften">Омекоти</string>
+    <string name="text_makeup_trimface">Разкрасяване на лицето</string>
+    <string name="text_makeup_bigeye">Големи очи</string>
+    <string name="truescanner_normal">Нормално</string>
+    <string name="truescanner_white">Бяла дъска</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Премахване на отблясъци</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">Гледай направо</string>
+    <string name="seestraight_input_image_is_small">Изображението е прекалено малко за обработка.</string>
+    <string name="seestraight_process_fail">Грешка при обработката на изображението.</string>
+    <string name="trim_video_exit_title">Отхвърляне на промените?</string>
+    <string name="trim_video_exit_msg">Да отхвърля ли промените направени по това видео?</string>
+    <string name="trim_video_exit_discard">ОТХВЪРЛИ</string>
+</resources>
diff --git a/res/values-bn/cm_strings.xml b/res/values-bn/cm_strings.xml
new file mode 100644
index 0000000..16abfed
--- /dev/null
+++ b/res/values-bn/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">রেকর্ডের সময়</string>
+</resources>
diff --git a/res/values-bn/codeaurora_strings.xml b/res/values-bn/codeaurora_strings.xml
new file mode 100644
index 0000000..86bfda2
--- /dev/null
+++ b/res/values-bn/codeaurora_strings.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ধাপ</string>
+    <string name="setp_option_three_second">৩ সেকেন্ড</string>
+    <string name="setp_option_six_second">৬ সেকেন্ড</string>
+    <string name="single_track">"একটি ট্র্যাক"</string>
+    <string name="next">"পরবর্তী"</string>
+    <string name="previous">"পূর্ববর্তী"</string>
+    <string name="setting">নিয়ন্ত্রণ</string>
+    <string name="media_controller_live">সরাসরি</string>
+    <string name="media_controller_playing">চলছে</string>
+    <string name="media_controller_connecting">সংযুক্ত করা হচ্ছে\u2026</string>
+    <string name="bookmark_title">"শিরোনাম"</string>
+    <string name="bookmark_location">"অবস্থান"</string>
+    <string name="delete_all">"সব মুছে ফেলুন"</string>
+    <string name="default_title">"পূর্ব-নির্ধারিত শিরনাম"</string>
+    <string name="more_image">আরো ছবি</string>
+    <string name="map_activity_not_found_err">অবস্থান দেখানোর জন্য কোনো মানচিত্র অ্যাপ ইনস্টল করা নেই।</string>
+</resources>
diff --git a/res/values-ca/cm_strings.xml b/res/values-ca/cm_strings.xml
new file mode 100644
index 0000000..57032b9
--- /dev/null
+++ b/res/values-ca/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Temps de gravació</string>
+</resources>
diff --git a/res/values-ca/codeaurora_strings.xml b/res/values-ca/codeaurora_strings.xml
new file mode 100644
index 0000000..ae1cd6a
--- /dev/null
+++ b/res/values-ca/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Pas</string>
+    <string name="step_option_desc">Personalitza el salt ràpid endavant/rebobina ràpid</string>
+    <string name="setp_option_three_second">3 segons</string>
+    <string name="setp_option_six_second">6 segons</string>
+    <string name="loop">"Bucle"</string>
+    <string name="single">"Individual"</string>
+    <string name="stereo">"Estèreo"</string>
+    <string name="speaker_on">Altaveu Activat</string>
+    <string name="speaker_off">Altaveu Desactivat</string>
+    <string name="speaker_need_headset">Endolla els auriculars per utilitzar aquesta característica.</string>
+    <string name="single_track">"Una pista"</string>
+    <string name="input_url">"Introdueix URL"</string>
+    <string name="streaming_settings">"Configuració de la transmissió"</string>
+    <string name="next">"Següent"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Mida del buffer</string>
+    <string name="apn">APN preferida</string>
+    <string name="rtp_min_port">Port min</string>
+    <string name="rtp_max_port">Port max</string>
+    <string name="set_rtp_min_port">Estableix el port min</string>
+    <string name="set_rtp_max_port">Estableix el port max</string>
+    <string name="set_buffer_size">Estableix la mida del buffer</string>
+    <string name="set_apn">Selecciona l\'APN preferida</string>
+    <string name="setting">Configuració</string>
+    <string name="server_timeout_title">"Temps d'espera del servidor"</string>
+    <string name="server_timeout_message">"vols tornar a connectar amb el servidor per reproduir el vídeo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"La connexió ha fallat, intentant tornar a connectar a %1$d\u2026"</string>
+    <string name="media_controller_live">En directe</string>
+    <string name="media_controller_playing">S\'està reproduïnt</string>
+    <string name="media_controller_connecting">S\'està connectant\u2026</string>
+    <string name="bookmark_add">"Afegeix un marcador"</string>
+    <string name="bookmark_display">"Mostra els marcadors"</string>
+    <string name="bookmark_empty">"Sense marcadors"</string>
+    <string name="bookmark_exist">"El marcador ja existeix"</string>
+    <string name="bookmark_add_success">"S'ha afegit un marcador"</string>
+    <string name="bookmark_list">"Marcadors"</string>
+    <string name="bookmark_title">"Títol"</string>
+    <string name="bookmark_location">"Ubicació"</string>
+    <string name="delete_all">"Esborrar-ho tot"</string>
+    <string name="default_title">"Títol predefinit"</string>
+    <string name="more_image">Més imatges</string>
+    <string name="mute_nosupport">No s\'ha pogut silenciar: vídeo no suportat</string>
+    <string name="map_activity_not_found_err">No hi ha cap aplicació de mapes instal·lada per mostrar la ubicació.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vídeo</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">El nombre màxim d\'elements seleccionats per compartir és 300</string>
+    <string name="share_dialogue_title">Comparteix via</string>
+    <string name="no_faces">Sense cares</string>
+    <string name="fail_trim">Ho sento, aquest fitxer de vídeo no es pot retallar</string>
+    <string name="can_not_trim">Només els fitxers mp4 i 3gp poden ser retallats</string>
+    <string name="drm_license_info">Informació de llicència DRM</string>
+    <string name="timeline_title">Línia de temps</string>
+    <string name="albums_title">Àlbums</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Vista de llista</string>
+    <string name="tvEmptyAlbum">No s\'ha trobat cap foto</string>
+    <string name="tvEmptyVideos">No s\'ha trobat cap vídeo</string>
+    <string name="text_makeup_whiten">Blanqueja</string>
+    <string name="text_makeup_Soften">Suavitza</string>
+    <string name="text_makeup_trimface">Retoc facial</string>
+    <string name="text_makeup_bigeye">Ulls grans</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Pissarra</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Elimina reflexos</string>
+    <string name="hazebuster_acts">Anti-calitja</string>
+    <string name="seestraight_acts">Veure directament</string>
+    <string name="seestraight_input_image_is_small">La imatge entrant es massa petita per a ser processada.</string>
+    <string name="seestraight_process_fail">No s\'ha pogut processar la imatge.</string>
+    <string name="trim_video_exit_title">Vols descartar els canvis?</string>
+    <string name="trim_video_exit_msg">Vols descartar els canvis fets a aquest vídeo?</string>
+    <string name="trim_video_exit_discard">DESCARTA</string>
+</resources>
diff --git a/res/values-cs/cm_strings.xml b/res/values-cs/cm_strings.xml
new file mode 100644
index 0000000..e30c4a7
--- /dev/null
+++ b/res/values-cs/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Čas nahrávky</string>
+</resources>
diff --git a/res/values-cs/codeaurora_strings.xml b/res/values-cs/codeaurora_strings.xml
new file mode 100644
index 0000000..b81ad62
--- /dev/null
+++ b/res/values-cs/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Krok</string>
+    <string name="step_option_desc">Přizpůsobit krok vpřed/vzad</string>
+    <string name="setp_option_three_second">3 sekundy</string>
+    <string name="setp_option_six_second">6 sekund</string>
+    <string name="loop">"Opakování"</string>
+    <string name="single">"Jednou"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Reproduktor zapnut</string>
+    <string name="speaker_off">Reproduktor vypnut</string>
+    <string name="speaker_need_headset">Pro využití této funkce připojte sluchátka.</string>
+    <string name="single_track">"Jedna stopa"</string>
+    <string name="input_url">"Zadejte URL"</string>
+    <string name="streaming_settings">"Nastavení pro datové toky"</string>
+    <string name="next">"Další"</string>
+    <string name="previous">"Předchozí"</string>
+    <string name="buffer_size">Velikost vyrovnávací paměti</string>
+    <string name="apn">Upřednostňované APN</string>
+    <string name="rtp_min_port">Min. č. portu</string>
+    <string name="rtp_max_port">Max. č. portu</string>
+    <string name="set_rtp_min_port">Nastavit min. č. portu</string>
+    <string name="set_rtp_max_port">Nastavit max. č. portu</string>
+    <string name="set_buffer_size">Nastavit velikost vyrovnávací paměťi</string>
+    <string name="set_apn">Vyberte upřednostňovaný APN</string>
+    <string name="setting">Nastavení</string>
+    <string name="server_timeout_title">"Časový limit serveru"</string>
+    <string name="server_timeout_message">"Znovu připojit k serveru a spustit video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Připojení se nezdařilo, pokus o obnovení spojení k „%1$d“\u2026"</string>
+    <string name="media_controller_live">Živě</string>
+    <string name="media_controller_playing">Přehrávání</string>
+    <string name="media_controller_connecting">Připojování\u2026</string>
+    <string name="bookmark_add">"Přidat záložku"</string>
+    <string name="bookmark_display">"Zobrazit záložky"</string>
+    <string name="bookmark_empty">"Žádné záložky"</string>
+    <string name="bookmark_exist">"Záložka již existuje"</string>
+    <string name="bookmark_add_success">"Založka přidána"</string>
+    <string name="bookmark_list">"Záložky"</string>
+    <string name="bookmark_title">"Název"</string>
+    <string name="bookmark_location">"Poloha"</string>
+    <string name="delete_all">"Odstranit vše"</string>
+    <string name="default_title">"Výchozí název"</string>
+    <string name="more_image">Další obrázky</string>
+    <string name="mute_nosupport">Nelze ztlumit: video není podporované</string>
+    <string name="map_activity_not_found_err">Není nainstalována žádná mapová aplikace pro zobrazení polohy.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="few">%1$d videa</item>
+        <item quantity="many">%1$d videí</item>
+        <item quantity="other">%1$d videí</item>
+    </plurals>
+    <string name="cannot_share_items">Maximální počet vybraných položek pro sdílení je 300</string>
+    <string name="share_dialogue_title">Sdílet pomocí</string>
+    <string name="no_faces">Žádné tváře</string>
+    <string name="fail_trim">Toto video nelze oříznout</string>
+    <string name="can_not_trim">Oříznout lze pouze soubory mp4 a 3gp</string>
+    <string name="drm_license_info">Informace o licenci DRM</string>
+    <string name="timeline_title">Časová osa</string>
+    <string name="albums_title">Alba</string>
+    <string name="videos_title">Videa</string>
+    <string name="action_viewtype_list">Zobrazení seznamu</string>
+    <string name="tvEmptyAlbum">Nebyly nalezeny žádné fotografie</string>
+    <string name="tvEmptyVideos">Nebyla nalezena žádná videa</string>
+    <string name="text_makeup_whiten">Bělení</string>
+    <string name="text_makeup_Soften">Změkčit</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Rybí oko</string>
+    <string name="truescanner_normal">Normálně</string>
+    <string name="truescanner_white">Bílá tabule</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Odstranit odlesky</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">Viz přímo</string>
+    <string name="seestraight_input_image_is_small">Vstupní obrázek je pro zpracování příliš malý.</string>
+    <string name="seestraight_process_fail">Obrázek nelze zpracovat.</string>
+    <string name="trim_video_exit_title">Zahodit změny?</string>
+    <string name="trim_video_exit_msg">Chcete zahodit změny provedené v tomto videu?</string>
+    <string name="trim_video_exit_discard">ZAHODIT</string>
+</resources>
diff --git a/res/values-cy/cm_strings.xml b/res/values-cy/cm_strings.xml
new file mode 100644
index 0000000..7e3313d
--- /dev/null
+++ b/res/values-cy/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Amser a recordiwyd</string>
+</resources>
diff --git a/res/values-cy/codeaurora_strings.xml b/res/values-cy/codeaurora_strings.xml
new file mode 100644
index 0000000..40a7b82
--- /dev/null
+++ b/res/values-cy/codeaurora_strings.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Cam</string>
+    <string name="step_option_desc">Addasu cam chwarae cyflym/chwarae nôl</string>
+    <string name="setp_option_three_second">3 eiliad</string>
+    <string name="setp_option_six_second">6 eiliad</string>
+    <string name="loop">"Dolen"</string>
+    <string name="single">"Sengl"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Seinydd YMLAEN</string>
+    <string name="speaker_off">Seinydd I FFWRDD</string>
+    <string name="speaker_need_headset">Cysyllta glustffonau i ddefnyddio\'r nodwedd hon.</string>
+    <string name="single_track">"Trac sengl"</string>
+    <string name="input_url">"Rho URL"</string>
+    <string name="streaming_settings">"Gosodiadau ffrydio"</string>
+    <string name="next">"Nesaf"</string>
+    <string name="previous">"Blaenorol"</string>
+    <string name="buffer_size">Maint byffer</string>
+    <string name="apn">APN a ffafrir</string>
+    <string name="rtp_min_port">Porth isaf</string>
+    <string name="rtp_max_port">Porth uchaf</string>
+    <string name="set_rtp_min_port">Gosod y porth isaf</string>
+    <string name="set_rtp_max_port">Gosod y porth uchaf</string>
+    <string name="set_buffer_size">Gosod maint byffer</string>
+    <string name="set_apn">Dewisa APN a ffafrir</string>
+    <string name="setting">Gosodiadau</string>
+    <string name="server_timeout_title">"Terfyn amser y gweinydd"</string>
+    <string name="server_timeout_message">"Ailgysylltu â'r gweinydd i chwarae'r fideo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Methodd y cysylltiad; yn ceisio cysylltu â %1$d\u2026"</string>
+    <string name="media_controller_live">Byw</string>
+    <string name="media_controller_playing">Yn chwarae</string>
+    <string name="media_controller_connecting">Yn cysylltu\u2026</string>
+    <string name="bookmark_add">"Ychwanegu nod tudalen"</string>
+    <string name="bookmark_display">"Dangos nodau tudalennau"</string>
+    <string name="bookmark_empty">"Dim nodau tudalennau"</string>
+    <string name="bookmark_exist">"Nod tudalen yn bodoli eisoes"</string>
+    <string name="bookmark_add_success">"Ychwanegwyd nod tudalen"</string>
+    <string name="bookmark_list">"Nodau tudalennau"</string>
+    <string name="bookmark_title">"Teitl"</string>
+    <string name="bookmark_location">"Lleoliad"</string>
+    <string name="delete_all">"Dileu'r cwbl"</string>
+    <string name="default_title">"Teitl rhagosodedig"</string>
+    <string name="more_image">Rhagor o ddelweddau</string>
+    <string name="mute_nosupport">Methu â distewi : ni chefnogir fideo</string>
+    <string name="map_activity_not_found_err">Does dim apiau mapio wedi eu gosod i fedru dangos y lleoliad.</string>
+    <plurals name="number_of_videos">
+        <item quantity="zero">%1$d fideos</item>
+        <item quantity="one">%1$d fideo</item>
+        <item quantity="two">%1$d fideo</item>
+        <item quantity="few">%1$d fideo</item>
+        <item quantity="many">%1$d fideo</item>
+        <item quantity="other">%1$d fideo</item>
+    </plurals>
+    <string name="cannot_share_items">Gellir ond rhannu hyd at 300 o eitemau</string>
+    <string name="share_dialogue_title">Rhannu drwy</string>
+    <string name="no_faces">Dim wynebau</string>
+    <string name="fail_trim">Ymddiheuriadau, ond ni ellir tocio\'r ffeil fideo hon</string>
+    <string name="can_not_trim">Dim ond ffeiliau mp4 a 3gp gellir eu tocio</string>
+    <string name="drm_license_info">Gwybodaeth trwydded DRM</string>
+    <string name="timeline_title">Llinell amser</string>
+    <string name="albums_title">Casgliadau</string>
+    <string name="videos_title">Fideos</string>
+    <string name="action_viewtype_list">Golwg rhestr</string>
+    <string name="tvEmptyAlbum">Ni chanfuwyd unrhyw luniau</string>
+    <string name="tvEmptyVideos">Ni chanfuwyd unrhyw fideos</string>
+    <string name="text_makeup_whiten">Gwynnu</string>
+    <string name="text_makeup_Soften">Lleddfu</string>
+    <string name="text_makeup_trimface">Trimwyneb</string>
+    <string name="text_makeup_bigeye">Llygaid mawrion</string>
+    <string name="truescanner_normal">Arferol</string>
+    <string name="truescanner_white">Bwrdd gwyn</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Tynnu llacharedd</string>
+    <string name="hazebuster_acts">Gwaredwr Tawch</string>
+    <string name="seestraight_acts">Gweld yn syth</string>
+    <string name="seestraight_input_image_is_small">Mae\'r ddelwedd mewnbwn rhy fach i\'w phrosesu.</string>
+    <string name="seestraight_process_fail">Methwyd â phrosesu\'r ddelwedd.</string>
+    <string name="trim_video_exit_title">Gwaredu â\'r newidiadau?</string>
+    <string name="trim_video_exit_msg">Cael gwared â\'r newidiadau i\'r fideo hwn?</string>
+    <string name="trim_video_exit_discard">GWAREDU</string>
+</resources>
diff --git a/res/values-cy/filtershow_strings.xml b/res/values-cy/filtershow_strings.xml
new file mode 100644
index 0000000..b719322
--- /dev/null
+++ b/res/values-cy/filtershow_strings.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">Golygydd Lluniau</string>
+    <string name="cannot_load_image">Methu â llwytho\'r ddelwedd!</string>
+    <string name="cannot_edit_original">Methu â golygu\'r gwreiddiol</string>
+    <string name="original_picture_text">@string/original</string>
+    <string name="setting_wallpaper">Yn gosod fel papur wal</string>
+    <string name="download_failure">Methwyd â lawrlwytho\'r llun. Rhwydwaith ddim ar gael.</string>
+    <string name="original">Gwreiddiol</string>
+    <string name="borders" msgid="4461692156695893616">Borderi</string>
+    <string name="custom_border">Addasedig</string>
+    <string name="filtershow_undo">Dadwneud</string>
+    <string name="filtershow_redo">Ail-wneud</string>
+    <string name="show_imagestate_panel">Dangos yr Effeithiau a Osodwyd</string>
+    <string name="hide_imagestate_panel">Cuddio\'r Effeithiau a Osodwyd</string>
+    <string name="export_image">Allforio</string>
+    <string name="print_image">Argraffu</string>
+    <string name="export_flattened">Allforio Delwedd wedi\'i Fflatio</string>
+    <string name="select_output_settings">Bydd y ddelwedd sy\'n cael ei allforio yn gopi, heb yr hanes.</string>
+    <string name="quality">Ansawdd</string>
+    <string name="size">Maint</string>
+    <string name="x">x</string>
+    <string name="menu_settings">Gosodiadau</string>
+    <string name="unsaved">Mae newidiadau i\'r ddelwedd hon heb eu cadw.</string>
+    <string name="save_before_exit">Wyt ti eisiau cadw cyn gadael?</string>
+    <string name="save_and_exit">Cadw a Gadael</string>
+    <string name="save_and_processing">Yn prosesu delwedd maint llawn...</string>
+    <string name="exit">Gadael</string>
+    <string name="history">Hanes</string>
+    <string name="reset">Ailosod</string>
+    <string name="history_original">@string/original</string>
+    <string name="imageState">Effeithiau a Osodwyd</string>
+    <string name="compare_original">Cymharu</string>
+    <string name="apply_effect">Gosod</string>
+    <string name="reset_effect">Ailosod</string>
+    <string name="aspect">Cymhareb</string>
+    <string name="aspect1to1_effect">1:1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">Dim</string>
+    <string name="aspectOriginal_effect">@string/original</string>
+    <string name="Fixed">Sefydlog</string>
+    <string name="tinyplanet">Planed Fychan</string>
+    <string name="exposure" msgid="1229093066434614811">Amlygiad</string>
+    <string name="sharpness">Awch</string>
+    <string name="contrast">Cyferbyniaeth</string>
+    <string name="vibrance">Cryfder Lliwiau</string>
+    <string name="saturation">Dyfnder Lliw</string>
+    <string name="bwfilter">Hidlydd DG</string>
+    <string name="wbalance">Awtoliw</string>
+    <string name="hue">Gwawr</string>
+    <string name="shadow_recovery">Cysgodion</string>
+    <string name="highlight_recovery">Goleubwyntio</string>
+    <string name="curvesRGB">Cromliniau</string>
+    <string name="vignette">Twll clo</string>
+    <string name="vignette_main">Twll clo</string>
+    <string name="vignette_exposure">Amlygiad</string>
+    <string name="vignette_saturation">Dyfnder Lliw</string>
+    <string name="vignette_contrast">Cyferbyniaeth</string>
+    <string name="vignette_falloff">Disgyn i ffwrdd</string>
+    <string name="redeye">Llygaid Cochion</string>
+    <string name="imageDraw">Darlunio</string>
+    <string name="straighten" msgid="5217801513491493491">Sythu</string>
+    <string name="crop" msgid="5584000454518174632">Tocio</string>
+    <string name="rotate" msgid="460017689320955494">Cylchdroi</string>
+    <string name="mirror">Fflipio</string>
+    <string name="negative">Negyddol</string>
+    <string name="none" msgid="3601545724573307541">Dim</string>
+    <string name="edge">Ymylon</string>
+    <string name="kmeans">Postereiddio</string>
+    <string name="downsample">Lawrsamplo</string>
+    <string name="grad">Graddedig</string>
+    <string name="editor_grad_brightness">Disgleirdeb</string>
+    <string name="editor_grad_contrast">Cyferbyniaeth</string>
+    <string name="editor_grad_saturation">Dyfnder Lliw</string>
+    <string name="editor_chan_sat_main">Prif</string>
+    <string name="editor_chan_sat_red">Coch</string>
+    <string name="editor_chan_sat_yellow">Melyn</string>
+    <string name="editor_chan_sat_green">Gwyrdd</string>
+    <string name="editor_chan_sat_cyan">Gwyrddlas</string>
+    <string name="editor_chan_sat_blue">Glas</string>
+    <string name="editor_chan_sat_magenta">Magenta</string>
+    <string name="editor_grad_style">Arddull</string>
+    <string name="editor_grad_new">newydd</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">Coch</string>
+    <string name="curves_channel_green">Gwyrdd</string>
+    <string name="curves_channel_blue">Glas</string>
+    <string name="draw_style">Arddull</string>
+    <string name="draw_size">Maint</string>
+    <string name="draw_hue">Gwawr</string>
+    <string name="draw_saturation">Dyfnder Lliw</string>
+    <string name="draw_value">Disgleirdeb</string>
+    <string name="draw_color">Lliw</string>
+    <string name="draw_style_line">Llinellau</string>
+    <string name="draw_style_brush_spatter">Marciwr</string>
+    <string name="draw_style_brush_marker">Ysgeintio</string>
+    <string name="draw_clear">Clirio</string>
+    <string name="color_border_size">Trwch</string>
+    <string name="color_border_corner_size">Maint Cornel</string>
+    <string name="color_border_color">Lliw</string>
+    <string name="color_border_clear">Clirio</string>
+    <string name="color_pick_select">Dewis lliw addasedig</string>
+    <string name="color_pick_title">Dewis Lliw</string>
+    <string name="draw_size_title">Dewis Maint</string>
+    <string name="draw_size_accept">Iawn</string>
+    <string name="state_panel_original">Gwreiddiol</string>
+    <string name="state_panel_result">Canlyniad</string>
+    <string name="filtershow_notification_label">Yn Cadw\'r Ddelwedd</string>
+    <string name="filtershow_notification_message">Yn prosesu...</string>
+    <string name="filtershow_save_preset">Cadw\'r rhagosodiad presennol</string>
+    <string name="filtershow_manage_preset">Rheoli rhagosoiadau defnyddiwr</string>
+    <string name="filtershow_new_preset">Rhagosodiad Newydd</string>
+    <string name="filtershow_preset_name">Enw\'r Rhagosodiad</string>
+    <string name="filtershow_show_info_panel">Gwybodaeth</string>
+    <string name="filtershow_show_info_panel_name">Enw Delwedd</string>
+    <string name="filtershow_show_info_panel_size">Maint Delwedd</string>
+    <string name="filtershow_show_info_panel_histogram">Histogram</string>
+    <string name="filtershow_show_info_panel_exif">Data EXIF</string>
+    <string name="filtershow_add_button_looks">Rhagosodiad</string>
+    <string name="filtershow_add_button_versions">Fersiwn</string>
+    <string name="filtershow_version_original">Gwreiddiol</string>
+    <string name="filtershow_version_current">Cyfredol</string>
+    <string name="filtershow_exif_model">Model</string>
+    <string name="filtershow_exif_aperture">Agorfa</string>
+    <string name="filtershow_exif_focal_length">Hyd Ffocal</string>
+    <string name="filtershow_exif_iso">ISO</string>
+    <string name="filtershow_exif_subject_distance">Pellter y Pwnc</string>
+    <string name="filtershow_exif_date">Dyddiad tynnwyd</string>
+    <string name="filtershow_exif_f_stop">F Stop</string>
+    <string name="filtershow_exif_exposure_time">Amser Amlygiad</string>
+    <string name="filtershow_exif_copyright">Hawlfraint</string>
+</resources>
diff --git a/res/values-cy/strings.xml b/res/values-cy/strings.xml
new file mode 100644
index 0000000..88a708f
--- /dev/null
+++ b/res/values-cy/strings.xml
@@ -0,0 +1,475 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Oriel</string>
+    <string name="gadget_title">Ffrâm llun</string>
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="movie_view_label">Chwaraeydd fideo</string>
+    <string name="loading_video">Yn llwytho fideo\u2026</string>
+    <string name="loading_image">Yn llwytho delwedd\u2026</string>
+    <string name="loading_account">Yn llwytho cyfrif\u2026</string>
+    <string name="resume_playing_title">Parhau i chwarae\'r fideo</string>
+    <string name="resume_playing_message">Parhau i chwarae o %s?</string>
+    <string name="resume_playing_resume">Parhau i chwarae</string>
+    <string name="loading">Yn llwytho\u2026</string>
+    <string name="fail_to_load">Methwyd â llwytho</string>
+    <string name="fail_to_load_image">Methwyd â llwytho\'r ddelwedd</string>
+    <string name="no_thumbnail">Dim mân-lun</string>
+    <string name="resume_playing_restart">Dechrau eto</string>
+    <string name="crop_save_text">Iawn</string>
+    <string name="ok">Iawn</string>
+    <string name="multiface_crop_help">Cyffyrdda wyneb i ddechrau.</string>
+    <string name="saving_image">Yn cadw\'r llun\u2026</string>
+    <string name="filtershow_saving_image">Yn cadw\'r llun i <xliff:g id="album_name">%1$s</xliff:g>\u2026</string>
+    <string name="save_error">Methwyd â chadw\'r ddelwedd wedi\'i thocio.</string>
+    <string name="crop_label">Tocio\'r llun</string>
+    <string name="trim_label">Tocio fideo</string>
+    <string name="select_image">Dewisa lun</string>
+    <string name="select_video">Dewisa fideo</string>
+    <string name="select_item">Dewis eitemau</string>
+    <string name="select_album">Dewisa albwm</string>
+    <string name="select_group">Dewisa grŵp</string>
+    <string name="set_image">Gosod y llun fel</string>
+    <string name="set_wallpaper">Gosod papur wal</string>
+    <string name="wallpaper">Wedi gosod fel papur wal\u2026</string>
+    <string name="camera_setas_wallpaper">Papur wal</string>
+    <string name="delete">Dileu</string>
+    <plurals name="delete_selection">
+        <item quantity="zero">Dileu\'r eitemau a ddewiswyd?</item>
+        <item quantity="one">Dileu\'r eitem a ddewiswyd?</item>
+        <item quantity="two">Dileu\'r eitemau a ddewiswyd?</item>
+        <item quantity="few">Dileu\'r eitemau a ddewiswyd?</item>
+        <item quantity="many">Dileu\'r eitemau a ddewiswyd?</item>
+        <item quantity="other">Dileu\'r eitemau a ddewiswyd?</item>
+    </plurals>
+    <string name="confirm">Cadarnhau</string>
+    <string name="cancel">Diddymu</string>
+    <string name="share">Rhannu</string>
+    <string name="share_panorama">Rhannu\'r panorama</string>
+    <string name="share_as_photo">Rhannu fel llun</string>
+    <string name="deleted">Dilëwyd</string>
+    <string name="undo">DADWNEUD</string>
+    <string name="select_all">Dewis y cyfan</string>
+    <string name="deselect_all">Dewis dim</string>
+    <string name="slideshow">Sioe sleidiau</string>
+    <string name="details">Manylion</string>
+    <string name="details_title">%1$d o %2$d eitem:</string>
+    <string name="close">Cau</string>
+    <string name="switch_to_camera">Newid i\'r Camera</string>
+    <plurals name="number_of_items_selected">
+        <item quantity="zero">%1$d wedi\'u dewis</item>
+        <item quantity="one">%1$d wedi\'i ddewis</item>
+        <item quantity="two">%1$d wedi\'u dewis</item>
+        <item quantity="few">%1$d wedi\'u dewis</item>
+        <item quantity="many">%1$d wedi\'u dewis</item>
+        <item quantity="other">%1$d wedi\'u dewis</item>
+    </plurals>
+    <plurals name="number_of_albums_selected">
+        <item quantity="zero">%1$d wedi\'u dewis</item>
+        <item quantity="one">%1$d wedi\'i ddewis</item>
+        <item quantity="two">%1$d wedi\'u dewis</item>
+        <item quantity="few">%1$d wedi\'u dewis</item>
+        <item quantity="many">%1$d wedi\'u dewis</item>
+        <item quantity="other">%1$d wedi\'u dewis</item>
+    </plurals>
+    <plurals name="number_of_groups_selected">
+        <item quantity="zero">%1$d wedi\'u dewis</item>
+        <item quantity="one">%1$d wedi\'i ddewis</item>
+        <item quantity="two">%1$d wedi\'u dewis</item>
+        <item quantity="few">%1$d wedi\'u dewis</item>
+        <item quantity="many">%1$d wedi\'u dewis</item>
+        <item quantity="other">%1$d wedi\'u dewis</item>
+    </plurals>
+    <string name="show_on_map">Dangos ar fap</string>
+    <string name="rotate_left">Cylchdroi\'n wrthglocwedd</string>
+    <string name="rotate_right">Cylchdroi\'n glocwedd</string>
+    <string name="no_such_item">Methwyd â dod o hyd iddynt.</string>
+    <string name="edit">Golygu</string>
+    <string name="simple_edit">Golygu syml</string>
+    <string name="process_caching_requests">Yn prosesu ceisiadau cadw i gof dros dro</string>
+    <string name="caching_label">Yn cofio dros dro\u2026</string>
+    <string name="crop_action">Tocio</string>
+    <string name="trim_action">Tocio</string>
+    <string name="mute_action">Distewi</string>
+    <string name="set_as">Gosod fel</string>
+    <string name="video_mute_err">Methu â distewi\'r fideo.</string>
+    <string name="video_err">Methu â chwarae\'r fideo.</string>
+    <string name="group_by_location">Yn ôl lleoliad</string>
+    <string name="group_by_time">Yn ôl amser</string>
+    <string name="group_by_tags">Yn ôl tagiau</string>
+    <string name="group_by_faces">Yn ôl pobol</string>
+    <string name="group_by_album">Yn ôl casgliad</string>
+    <string name="group_by_size">Yn ôl maint</string>
+    <string name="untagged">Heb dagiau</string>
+    <string name="no_location">Dim lleoliad</string>
+    <string name="no_connectivity">Methwyd ag adnabod rhai lleoliadau oherwydd problemau rhwydwaith.</string>
+    <string name="sync_album_error">Methwyd â lawrlwytho\'r lluniau yn y casgliad hwn. Rho gynnig arall arni\'n hwyrach.</string>
+    <string name="show_images_only">Delwedau yn unig</string>
+    <string name="show_videos_only">Fideos yn unig</string>
+    <string name="show_all">Delweddau a fideos</string>
+    <string name="appwidget_title">Oriel Lluniau</string>
+    <string name="appwidget_empty_text">Dim lluniau.</string>
+    <string name="crop_saved">Cadwyd y ddelwedd wedi\'i thocio yn <xliff:g id="folder_name">%s</xliff:g>.</string>
+    <string name="no_albums_alert">Dim casgliadau ar gael.</string>
+    <string name="empty_album">Dim delweddau/fideos ar gael.</string>
+    <string name="picasa_posts">Postiau</string>
+    <string name="make_available_offline">Gwneud ar gael all-lein</string>
+    <string name="sync_picasa_albums">Ail-gysoni</string>
+    <string name="done">Iawn</string>
+    <string name="sequence_in_set">%1$d o %2$d eitem:</string>
+    <string name="title">Teitl</string>
+    <string name="description">Disgrifiad</string>
+    <string name="time">Amser</string>
+    <string name="location">Lleoliad</string>
+    <string name="path">Llwybr</string>
+    <string name="width">Lled</string>
+    <string name="height">Uchder</string>
+    <string name="orientation">Gorweddiad</string>
+    <string name="duration">Hyd</string>
+    <string name="mimetype">Math MIME</string>
+    <string name="file_size">Maint ffeil</string>
+    <string name="maker">Gwneuthurwr</string>
+    <string name="model">Model</string>
+    <string name="flash">Fflach</string>
+    <string name="aperture">Agorfa</string>
+    <string name="focal_length">Hyd Ffocal</string>
+    <string name="white_balance">Cydbwysedd Gwyn</string>
+    <string name="exposure_time">Amser Amlygiad</string>
+    <string name="iso">ISO</string>
+    <string name="unit_mm">me</string>
+    <string name="manual">Â llaw</string>
+    <string name="auto">Awto</string>
+    <string name="flash_on">Taniodd y fflach</string>
+    <string name="flash_off">Dim fflach</string>
+    <string name="unknown">Anhysybys</string>
+    <string name="ffx_original">Gwreiddiol</string>
+    <string name="ffx_vintage">Hen</string>
+    <string name="ffx_instant">Polaroid</string>
+    <string name="ffx_bleach">Diliwio</string>
+    <string name="ffx_blue_crush">Glas</string>
+    <string name="ffx_bw_contrast">D/G</string>
+    <string name="ffx_punch">Pwnsh</string>
+    <string name="ffx_x_process">Proses X</string>
+    <string name="ffx_washout">Latte</string>
+    <string name="ffx_washout_color">Litho</string>
+    <plurals name="make_albums_available_offline">
+        <item quantity="zero">Yn gwneud albymau ar gael all-lein.</item>
+        <item quantity="one">Yn gwneud y casgliad ar gael all-lein.</item>
+        <item quantity="two">Yn gwneud casgliadau ar gael all-lein.</item>
+        <item quantity="few">Yn gwneud casgliadau ar gael all-lein.</item>
+        <item quantity="many">Yn gwneud casgliadau ar gael all-lein.</item>
+        <item quantity="other">Yn gwneud casgliadau ar gael all-lein.</item>
+    </plurals>
+    <string name="try_to_set_local_album_available_offline">Mae\'r eitem hon wedi ei gadw\'n lleol ac ar gael all-lein.</string>
+    <string name="set_label_all_albums">Pob casgliad</string>
+    <string name="set_label_local_albums">Casgliadau lleol</string>
+    <string name="set_label_mtp_devices">Dyfeisiau MTP</string>
+    <string name="set_label_picasa_albums">Casgliadau Picasa</string>
+    <string name="free_space_format"><xliff:g id="bytes">%s</xliff:g> ar gael</string>
+    <string name="size_below"><xliff:g id="size">%1$s</xliff:g> neu lai</string>
+    <string name="size_above"><xliff:g id="size">%1$s</xliff:g> neu fwy</string>
+    <string name="size_between"><xliff:g id="min_size">%1$s</xliff:g> i <xliff:g id="max_size">%2$s</xliff:g></string>
+    <string name="Import">Mewnforio</string>
+    <string name="import_complete">Cwblhawyd mewnforio</string>
+    <string name="import_fail">Methwyd â mewnforio</string>
+    <string name="camera_connected">Camera wedi\'i gysylltu.</string>
+    <string name="camera_disconnected">Camera wedi\'i datgysylltu.</string>
+    <string name="click_import">Cyffyrdda yma i fewnforio</string>
+    <string name="widget_type_album">Dewis casgliad</string>
+    <string name="widget_type_shuffle">Cymysgu\'r holl ddelweddau</string>
+    <string name="widget_type_photo">Dewis delwedd</string>
+    <string name="widget_type">Dewis delweddau</string>
+    <string name="slideshow_dream_name">Sioe sleidiau</string>
+    <string name="albums">Casgliadau</string>
+    <string name="times">Amseroedd</string>
+    <string name="locations">Lleoliadau</string>
+    <string name="people">Pobol</string>
+    <string name="tags">Tagiau</string>
+    <string name="group_by">Grŵpio fesul</string>
+    <string name="settings">Gosodiadau</string>
+    <string name="add_account">Ychwanegu cyfrif</string>
+    <string name="folder_camera">Camera</string>
+    <string name="folder_download">Lawrlwytho</string>
+    <string name="folder_edited_online_photos">Lluniau a olygwyd ar-lein</string>
+    <string name="folder_imported">Mewnforwyd</string>
+    <string name="folder_screenshot">Sgrinlun</string>
+    <string name="help">Cymorth</string>
+    <string name="no_external_storage_title">Dim Storfa</string>
+    <string name="no_external_storage">Does dim storfa allanol ar gael</string>
+    <string name="switch_photo_filmstrip">Golwg stribed ffilm</string>
+    <string name="switch_photo_grid">Golwg grid</string>
+    <string name="switch_photo_fullscreen">Golwg sgrin lawn</string>
+    <string name="trimming">Yn tocio</string>
+    <string name="muting">Yn distewi</string>
+    <string name="please_wait">Arhosa</string>
+    <string name="save_into">Yn cadw\'r fideo i <xliff:g id="album_name">%1$s</xliff:g>\u2026</string>
+    <string name="trim_too_short">Methwyd â thocio: mae\'r fideo targed yn rhy fyr</string>
+    <string name="pano_progress_text">Yn rendro panorama</string>
+    <string name="save" msgid="8140440041190264400">Cadw</string>
+    <string name="ingest_import">@string/Import</string>
+    <string name="ingest_import_complete">@string/import_complete</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">Yn sganio cynnwys...</string>
+    <plurals name="ingest_number_of_items_scanned">
+        <item quantity="zero">%1$d eitemau wedi\'u sganio</item>
+        <item quantity="one">%1$d eitem wedi\'i sganio</item>
+        <item quantity="two">%1$d eitem wedi\'u sganio</item>
+        <item quantity="few">%1$d eitem wedi\'u sganio</item>
+        <item quantity="many">%1$d eitem wedi\'u sganio</item>
+        <item quantity="other">%1$d eitem wedi\'u sganio</item>
+    </plurals>
+    <plurals name="ingest_number_of_items_selected">
+        <item quantity="zero">%1$d eitemau wedi\'u dewis</item>
+        <item quantity="one">%1$d eitem wedi\'i ddewis</item>
+        <item quantity="two">%1$d eitem wedi\'u dewis</item>
+        <item quantity="few">%1$d eitem wedi\'u dewis</item>
+        <item quantity="many">%1$d eitem wedi\'u dewis</item>
+        <item quantity="other">%1$d eitem wedi\'u dewis</item>
+    </plurals>
+    <string name="ingest_sorting" msgid="624687230903648118">Yn trefnu...</string>
+    <string name="ingest_scanning_done">Cwblhawyd sganio</string>
+    <string name="ingest_importing">Yn mewnforio...</string>
+    <string name="ingest_empty_device">Does dim cynnwys ar gael i\'w mewnforio ar y ddyfais hon.</string>
+    <string name="ingest_no_device">Does dim dyfais MTP wedi\'i chysylltu.</string>
+    <string name="ingest_switch_photo_grid">@string/switch_photo_grid</string>
+    <string name="ingest_switch_photo_fullscreen">@string/switch_photo_fullscreen</string>
+    <string name="camera_error_title">Gwall camera</string>
+    <string name="cannot_connect_camera">Methu â chysylltu â\'r camera.</string>
+    <string name="camera_disabled">Mae\'r camera wedi\'i analluogi oherwydd polisïau diogelwch.</string>
+    <string name="camera_label">Camera</string>
+    <string name="wait">Arhosa\u2026</string>
+    <string name="no_storage" product="nosdcard">Gosoda storfa USB cyn defnyddio\'r camera.</string>
+    <string name="no_storage" product="default">Gosoda gerdyn SD cyn defnyddio\'r camera.</string>
+    <string name="preparing_sd" product="nosdcard">Yn paratoi\'r storfa USB\u2026</string>
+    <string name="preparing_sd" product="default">Yn paratoi\'r cerdyn SD\u2026</string>
+    <string name="access_sd_fail" product="nosdcard">Methwyd â chael at y storfa USB.</string>
+    <string name="access_sd_fail" product="default">Methwyd â chael at y cerdyn SD.</string>
+    <string name="review_cancel">DIDDYMU</string>
+    <string name="review_ok">IAWN</string>
+    <string name="time_lapse_title">Yn recordio treigl amser</string>
+    <string name="pref_camera_id_title">Dewis camera</string>
+    <string name="pref_camera_id_entry_back">Nôl</string>
+    <string name="pref_camera_id_entry_front">Blaen</string>
+    <string name="pref_camera_recordlocation_title">Lleoliad cadw</string>
+    <string name="pref_camera_location_label">LLEOLIAD</string>
+    <string name="pref_camera_timer_title">Amserydd cyfrif i lawr</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="zero">%d eiliadau</item>
+        <item quantity="one">1 eiliad</item>
+        <item quantity="two">%d eiliad</item>
+        <item quantity="few">%d eiliad</item>
+        <item quantity="many">%d eiliad</item>
+        <item quantity="other">%d eiliad</item>
+    </plurals>
+    <string name="pref_camera_timer_sound_default">@string/setting_on_value</string>
+    <string name="pref_camera_timer_sound_title">Bipio wrth gyfrif i lawr</string>
+    <string name="setting_off">I ffwrdd</string>
+    <string name="setting_on">Ymlaen</string>
+    <string name="pref_video_quality_title">Ansawdd fideo</string>
+    <string name="pref_video_quality_entry_high">Uchel</string>
+    <string name="pref_video_quality_entry_low">Isel</string>
+    <string name="pref_video_time_lapse_frame_interval_title">Treigl amser</string>
+    <string name="pref_camera_settings_category">Gosodiadau camera</string>
+    <string name="pref_camcorder_settings_category">Gosodiadau fideo</string>
+    <string name="pref_camera_picturesize_title">Maint llun</string>
+    <string name="pref_camera_picturesize_entry_13mp">13M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_8mp">8M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_5mp">5M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_4mp">4M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_3mp">3M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_2mp">2M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">2M o bicseli (16:9)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">1.3M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_1mp">1M o bicseli</string>
+    <string name="pref_camera_picturesize_entry_vga">VGA</string>
+    <string name="pref_camera_picturesize_entry_qvga">QVGA</string>
+    <string name="pref_camera_focusmode_title">Modd ffocysu</string>
+    <string name="pref_camera_focusmode_entry_auto">Awto</string>
+    <string name="pref_camera_focusmode_entry_infinity">Anfeidredd</string>
+    <string name="pref_camera_focusmode_entry_macro">Macro</string>
+    <string name="pref_camera_focusmode_label_auto">AWTO</string>
+    <string name="pref_camera_focusmode_label_infinity">ANFEIDREDD</string>
+    <string name="pref_camera_focusmode_label_macro">MACRO</string>
+    <string name="pref_camera_flashmode_title">Modd fflachio</string>
+    <string name="pref_camera_flashmode_label">MODD FFLACHIO</string>
+    <string name="pref_camera_flashmode_entry_auto">Awto</string>
+    <string name="pref_camera_flashmode_entry_on">Ymlaen</string>
+    <string name="pref_camera_flashmode_entry_off">I ffwrdd</string>
+    <string name="pref_camera_flashmode_label_auto">FFLACH - AWTO</string>
+    <string name="pref_camera_flashmode_label_on">FFLACH - GORFODI</string>
+    <string name="pref_camera_flashmode_label_off">FFLACH - DIM</string>
+    <string name="pref_camera_whitebalance_title">Cydbwysedd Gwyn</string>
+    <string name="pref_camera_whitebalance_label">CYDBWYSEDD GWYN</string>
+    <string name="pref_camera_whitebalance_entry_auto">Awto</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">Gwynias</string>
+    <string name="pref_camera_whitebalance_entry_daylight">Golau dydd</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">Fflwroleuol</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">Cymylog</string>
+    <string name="pref_camera_whitebalance_label_auto">AWTO</string>
+    <string name="pref_camera_whitebalance_label_incandescent">GWYNIAS</string>
+    <string name="pref_camera_whitebalance_label_daylight">GOLAU DYDD</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">FFLWROLEUOL</string>
+    <string name="pref_camera_whitebalance_label_cloudy">CYMYLOG</string>
+    <string name="pref_camera_scenemode_title">Modd olygfa</string>
+    <string name="pref_camera_scenemode_entry_auto">Awto</string>
+    <string name="pref_camera_scenemode_entry_hdr">HDR</string>
+    <string name="pref_camera_scenemode_entry_action">Symudiad</string>
+    <string name="pref_camera_scenemode_entry_night">Nos</string>
+    <string name="pref_camera_scenemode_entry_sunset">Machlud</string>
+    <string name="pref_camera_scenemode_entry_party">Parti</string>
+    <string name="pref_camera_scenemode_label_auto">DIM</string>
+    <string name="pref_camera_scenemode_label_action">SYMUD</string>
+    <string name="pref_camera_scenemode_label_night">NOS</string>
+    <string name="pref_camera_scenemode_label_sunset">MACHLUD</string>
+    <string name="pref_camera_scenemode_label_party">PARTI</string>
+    <string name="pref_camera_countdown_label">AMSERYDD CYFRIF I LAWR</string>
+    <string name="pref_camera_countdown_label_off">AMSERYDD I FFWRDD</string>
+    <string name="pref_camera_countdown_label_one">1 EILIAD</string>
+    <string name="pref_camera_countdown_label_three">3 EILIAD</string>
+    <string name="pref_camera_countdown_label_ten">10 EILIAD</string>
+    <string name="pref_camera_countdown_label_fifteen">15 EILIAD</string>
+    <string name="not_selectable_in_scene_mode">Nid yw\'n bosib ei ddewis mewn modd golygfa.</string>
+    <string name="pref_exposure_title">Amlygiad</string>
+    <string name="pref_exposure_label">AMLYGIAD</string>
+    <string name="pref_camera_hdr_default">@string/setting_off_value</string>
+    <string name="pref_camera_hdr_label">HDR</string>
+    <string name="pref_camera_id_label_back">CAMERA BLAEN</string>
+    <string name="pref_camera_id_label_front">CAMERA CEFN</string>
+    <string name="dialog_ok">Iawn</string>
+    <string name="spaceIsLow_content" product="nosdcard">Mae dy storfa USB yn rhedeg yn brin o le. Newidia\'r gosodiad ansawdd neu ddileu rhai delweddau neu ffeiliau eraill.</string>
+    <string name="spaceIsLow_content" product="default">Mae dy gerdyn SD yn rhedeg yn brin o le. Newidia\'r gosodiad ansawdd neu ddileu rhai delweddau neu ffeiliau eraill.</string>
+    <string name="video_reach_size_limit">Wedi cyrraedd y terfyn maint.</string>
+    <string name="pano_too_fast_prompt">Rhy gyflym</string>
+    <string name="pano_dialog_prepare_preview">Yn paratoi panorama</string>
+    <string name="pano_dialog_panorama_failed">Methwyd â chadw panorama.</string>
+    <string name="pano_dialog_title">Panorama</string>
+    <string name="pano_capture_indication">Yn cipio panorama</string>
+    <string name="pano_dialog_waiting_previous">Yn disgwyl am y panorama blaenorol</string>
+    <string name="pano_review_saving_indication_str">Yn cadw\u2026</string>
+    <string name="pano_review_rendering">Yn rendro panorama</string>
+    <string name="tap_to_focus">Cyffyrdda i ffocysu.</string>
+    <string name="pref_video_effect_title">Effeithiau</string>
+    <string name="effect_none">Dim</string>
+    <string name="effect_goofy_face_squeeze">Gwasgu</string>
+    <string name="effect_goofy_face_big_eyes">Llygaid mawr</string>
+    <string name="effect_goofy_face_big_mouth">Ceg fawr</string>
+    <string name="effect_goofy_face_small_mouth">Ceg fach</string>
+    <string name="effect_goofy_face_big_nose">Trwyn mawr</string>
+    <string name="effect_goofy_face_small_eyes">Llygaid bach</string>
+    <string name="effect_backdropper_space">Yn y gofod</string>
+    <string name="effect_backdropper_sunset">Machlud</string>
+    <string name="effect_backdropper_gallery">Dy fideo</string>
+    <string name="bg_replacement_message">Rho dy ddyfais i lawr.\nCama allan o olwg am foment.</string>
+    <string name="video_snapshot_hint">Cyffyrdda i dynnu llun wrth recordio.</string>
+    <string name="video_recording_started">Mae recordio fideo wedi dechrau.</string>
+    <string name="video_recording_stopped">Mae recordio fideo wedi stopio.</string>
+    <string name="disable_video_snapshot_hint">Mae cipio fideo wedi\'i analluogi tra bod effeithiau arbennig ymlaen.</string>
+    <string name="clear_effects">Clirio effeithiau</string>
+    <string name="effect_silly_faces">WYNEBAU GWIRION</string>
+    <string name="effect_background">CEFNDIR</string>
+    <string name="accessibility_shutter_button">Botwm caead</string>
+    <string name="accessibility_menu_button">Botwm dewislen</string>
+    <string name="accessibility_review_thumbnail">Llun mwyaf diweddar</string>
+    <string name="accessibility_camera_picker">Botwm newid rhwng camera blaen a chefn</string>
+    <string name="accessibility_mode_picker">Dewisydd camera, fideo, neu banorama</string>
+    <string name="accessibility_second_level_indicators">Rhagor o reolyddion gosodiadau</string>
+    <string name="accessibility_back_to_first_level">Cau rheolyddion gosodiadau</string>
+    <string name="accessibility_zoom_control">Rheolydd chwyddo</string>
+    <string name="accessibility_decrement">Lleihau %1$s</string>
+    <string name="accessibility_increment">Cynyddu %1$s</string>
+    <string name="accessibility_check_box">%1$s blwch tic</string>
+    <string name="accessibility_switch_to_camera">Newid i lun</string>
+    <string name="accessibility_switch_to_video">Newid i fideo</string>
+    <string name="accessibility_switch_to_panorama">Newid i banorama</string>
+    <string name="accessibility_switch_to_new_panorama">Newid i banorama newydd</string>
+    <string name="accessibility_switch_to_refocus">Botwm Ailffocysu</string>
+    <string name="accessibility_review_cancel">Diddymu adolygu</string>
+    <string name="accessibility_review_ok">Wedi gorffen adolygu</string>
+    <string name="accessibility_review_retake">Adolygu eto</string>
+    <string name="accessibility_play_video">Chwarae fideo</string>
+    <string name="accessibility_pause_video">Atal fideo</string>
+    <string name="accessibility_reload_video">Ail-lwytho\'r fideo</string>
+    <string name="accessibility_time_bar">Bar amser y chwaraeydd fideo</string>
+    <string name="capital_on">YMLAEN</string>
+    <string name="capital_off">I FFWRDD</string>
+    <string name="pref_video_time_lapse_frame_interval_off">I ffwrdd</string>
+    <string name="pref_video_time_lapse_frame_interval_500">0.5 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">1.5 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2.5 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 eiliad</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">0.5 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">1 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">1.5 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 funud</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2.5 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 munud</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">0.5 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">1.5 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2.5 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 awr</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 awr</string>
+    <string name="time_lapse_seconds">eiliadau</string>
+    <string name="time_lapse_minutes">munudau</string>
+    <string name="time_lapse_hours">oriau</string>
+    <string name="time_lapse_interval_set">Iawn</string>
+    <string name="set_time_interval">Gosod Ysbaid Amser</string>
+    <string name="set_time_interval_help">Mae\'r nodwedd treigl amser i ffwrdd. Rhaid ei droi ymlaen i osod ysbaid amser.</string>
+    <string name="set_timer_help">Mae\'r amserydd cyfri i lawr i ffwrdd. Rhaid ei droi ymlaen er mwyn cyfrif i lawr cyn tynnu llun.</string>
+    <string name="set_duration">Gosod yr hyd mewn eiliadau</string>
+    <string name="count_down_title_text">Yn cyfrif i lawr i dynnu llun</string>
+    <string name="remember_location_title">Cofio lleoliadau cymryd lluniau?</string>
+    <string name="remember_location_prompt">Tagia dy luniau a fideos gyda\'r lleoliadau ble\'i tynnwyd.\n\nGall apiau eraill gweld y fath wybodaeth gyda\'r delweddau.</string>
+    <string name="remember_location_no">Dim diolch</string>
+    <string name="remember_location_yes">Ydw</string>
+    <string name="menu_camera">Camera</string>
+    <string name="menu_search">Chwilio</string>
+    <string name="tab_photos">Lluniau</string>
+    <string name="tab_albums">Casgliadau</string>
+    <string name="camera_menu_more_label">RHAGOR O DDEWISIADAU</string>
+    <string name="camera_menu_settings_label">GOSODIADAU</string>
+    <plurals name="number_of_photos">
+        <item quantity="zero">%1$d lluniau</item>
+        <item quantity="one">%1$d llun</item>
+        <item quantity="two">%1$d lun</item>
+        <item quantity="few">%1$d llun</item>
+        <item quantity="many">%1$d llun</item>
+        <item quantity="other">%1$d llun</item>
+    </plurals>
+</resources>
diff --git a/res/values-da/cm_strings.xml b/res/values-da/cm_strings.xml
new file mode 100644
index 0000000..21e14a4
--- /dev/null
+++ b/res/values-da/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Optagelsestidspunkt</string>
+</resources>
diff --git a/res/values-da/codeaurora_strings.xml b/res/values-da/codeaurora_strings.xml
new file mode 100644
index 0000000..a370649
--- /dev/null
+++ b/res/values-da/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Trin</string>
+    <string name="step_option_desc">Tilpas frem- og tilbagespolingstrin</string>
+    <string name="setp_option_three_second">3 sekunder</string>
+    <string name="setp_option_six_second">6 sekunder</string>
+    <string name="loop">"Sløjfe"</string>
+    <string name="single">"Enkelt"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Højtaler TIL</string>
+    <string name="speaker_off">Højtaler FRA</string>
+    <string name="speaker_need_headset">Tilslut hovedtelefoner, for at benytte denne funktion.</string>
+    <string name="single_track">"Enkelt spor"</string>
+    <string name="input_url">"Indtast URL"</string>
+    <string name="streaming_settings">"Transmissionsindstillinger"</string>
+    <string name="next">"Næste"</string>
+    <string name="previous">"Forrige"</string>
+    <string name="buffer_size">Arbejdslager-størrelse</string>
+    <string name="apn">Foretrukken APN</string>
+    <string name="rtp_min_port">Min. port</string>
+    <string name="rtp_max_port">Maks. port</string>
+    <string name="set_rtp_min_port">Angiv min. port</string>
+    <string name="set_rtp_max_port">Angiv maks. port</string>
+    <string name="set_buffer_size">Angiv arbejdslager-størrelse</string>
+    <string name="set_apn">Vælg foretrukken APN</string>
+    <string name="setting">Indstillinger</string>
+    <string name="server_timeout_title">"Server-tidsudløb"</string>
+    <string name="server_timeout_message">"Genopret forbindelsen til serveren, for at afspille videoen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Forbindelse fejlede, prøver at genoprette forbindelse til %1$d\u2026"</string>
+    <string name="media_controller_live">Direkte</string>
+    <string name="media_controller_playing">Afspiller</string>
+    <string name="media_controller_connecting">Forbinder\u2026</string>
+    <string name="bookmark_add">"Tilføj bogmærke"</string>
+    <string name="bookmark_display">"Vis bogmærker"</string>
+    <string name="bookmark_empty">"Ingen bogmærker"</string>
+    <string name="bookmark_exist">"Bogmærke eksisterer allerede"</string>
+    <string name="bookmark_add_success">"Bogmærke tilføjet"</string>
+    <string name="bookmark_list">"Bogmærker"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Lokalitet"</string>
+    <string name="delete_all">"Slet alle"</string>
+    <string name="default_title">"Standardtitel"</string>
+    <string name="more_image">Flere billeder</string>
+    <string name="mute_nosupport">Kan ikke gøre lydløs : video understøttes ikke</string>
+    <string name="map_activity_not_found_err">Der er ikke nogen kort-app installeret, til at vise lokaliteten.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videoer</item>
+    </plurals>
+    <string name="cannot_share_items">Maksimalt antal markerede elementer til deling er 300</string>
+    <string name="share_dialogue_title">Del via</string>
+    <string name="no_faces">Ingen ansigter</string>
+    <string name="fail_trim">Beklager, denne videofil kan ikke trimmes</string>
+    <string name="can_not_trim">Det er kun mp4- og 3gp-filer, der kan trimmes</string>
+    <string name="drm_license_info">DRM-licensinfo</string>
+    <string name="timeline_title">Tidslinje</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videoer</string>
+    <string name="action_viewtype_list">Listevisning</string>
+    <string name="tvEmptyAlbum">Ingen fotos fundet</string>
+    <string name="tvEmptyVideos">Ingen videoer fundet</string>
+    <string name="text_makeup_whiten">Blegning</string>
+    <string name="text_makeup_Soften">Blødgøring</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Fjern genskin</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">Se lige</string>
+    <string name="seestraight_input_image_is_small">Input-billedet er for lille til at behandle.</string>
+    <string name="seestraight_process_fail">Billedet kunne ikke behandles.</string>
+    <string name="trim_video_exit_title">Kassér ændringer?</string>
+    <string name="trim_video_exit_msg">Vil du kassere dine ændringer til denne video?</string>
+    <string name="trim_video_exit_discard">KASSÉR</string>
+</resources>
diff --git a/res/values-de/cm_strings.xml b/res/values-de/cm_strings.xml
new file mode 100644
index 0000000..5079aa3
--- /dev/null
+++ b/res/values-de/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Aufzeichnungszeit</string>
+</resources>
diff --git a/res/values-de/codeaurora_strings.xml b/res/values-de/codeaurora_strings.xml
new file mode 100644
index 0000000..9e6dd42
--- /dev/null
+++ b/res/values-de/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Schritt</string>
+    <string name="step_option_desc">Vor- und Zurückspul-Schritt anpassen</string>
+    <string name="setp_option_three_second">3 Sekunden</string>
+    <string name="setp_option_six_second">6 Sekunden</string>
+    <string name="loop">"Endlosschleife"</string>
+    <string name="single">"Einzeln"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Lautsprecher AN</string>
+    <string name="speaker_off">Lautsprecher AUS</string>
+    <string name="speaker_need_headset">Für diese Funktionen müssen Sie Kopfhörer verwenden.</string>
+    <string name="single_track">"Einzelner Titel"</string>
+    <string name="input_url">"Geben Sie eine URL ein."</string>
+    <string name="streaming_settings">"Streaming-Einstellungen"</string>
+    <string name="next">"Weiter"</string>
+    <string name="previous">"Zurück"</string>
+    <string name="buffer_size">Puffergröße</string>
+    <string name="apn">Bevorzugter APN</string>
+    <string name="rtp_min_port">Min. Wert für Port</string>
+    <string name="rtp_max_port">Max. Wert für Port</string>
+    <string name="set_rtp_min_port">Min. Wert für Port festlegen</string>
+    <string name="set_rtp_max_port">Max. Wert für Port festlegen</string>
+    <string name="set_buffer_size">Puffergröße einstellen</string>
+    <string name="set_apn">Bevorzugten APN auswählen</string>
+    <string name="setting">Einstellungen</string>
+    <string name="server_timeout_title">"Zeitüberschreitung beim Server"</string>
+    <string name="server_timeout_message">"Erneut zum Server verbinden, um das Video abzuspielen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Verbindung fehlgeschlagen, neuer Verbindungsversuch zu %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Derzeit läuft</string>
+    <string name="media_controller_connecting">Verbindung wird hergestellt\u2026</string>
+    <string name="bookmark_add">"Lesezeichen hinzufügen"</string>
+    <string name="bookmark_display">"Lesezeichen anzeigen"</string>
+    <string name="bookmark_empty">"Keine Lesezeichen"</string>
+    <string name="bookmark_exist">"Lesezeichen ist bereits vorhanden"</string>
+    <string name="bookmark_add_success">"Lesezeichen hinzugefügt"</string>
+    <string name="bookmark_list">"Lesezeichen"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Ort"</string>
+    <string name="delete_all">"Alle löschen"</string>
+    <string name="default_title">"Standardtitel"</string>
+    <string name="more_image">Weitere Bilder</string>
+    <string name="mute_nosupport">Stummschalten nicht möglich – das Video wird nicht unterstützt.</string>
+    <string name="map_activity_not_found_err">Es ist keine Karten-App zum Anzeigen des Standorts installiert.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d Video</item>
+        <item quantity="other">%1$d Videos</item>
+    </plurals>
+    <string name="cannot_share_items">Maximal 300 Elemente können geteilt werden</string>
+    <string name="share_dialogue_title">Teilen über</string>
+    <string name="no_faces">Keine Gesichter</string>
+    <string name="fail_trim">Diese Videodatei kann nicht gekürzt werden.</string>
+    <string name="can_not_trim">Nur MP4- und 3GP-Dateien können gekürzt werden</string>
+    <string name="drm_license_info">DRM-Lizenzinformationen</string>
+    <string name="timeline_title">Zeitverlauf</string>
+    <string name="albums_title">Alben</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">Listenansicht</string>
+    <string name="tvEmptyAlbum">Keine Fotos gefunden</string>
+    <string name="tvEmptyVideos">Keine Videos gefunden</string>
+    <string name="text_makeup_whiten">Aufhellen</string>
+    <string name="text_makeup_Soften">Weichzeichnen</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Große Augen</string>
+    <string name="truescanner_normal">Standard</string>
+    <string name="truescanner_white">Weißwandtafel</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Reflexionen entfernen</string>
+    <string name="hazebuster_acts">Dunstfilter</string>
+    <string name="seestraight_acts">SeeStraight</string>
+    <string name="seestraight_input_image_is_small">Bild ist zu klein zur Bearbeitung.</string>
+    <string name="seestraight_process_fail">Bild konnte nicht verarbeitet werden.</string>
+    <string name="trim_video_exit_title">Änderungen verwerfen?</string>
+    <string name="trim_video_exit_msg">Änderungen am Video verwerfen?</string>
+    <string name="trim_video_exit_discard">VERWERFEN</string>
+</resources>
diff --git a/res/values-el/cm_strings.xml b/res/values-el/cm_strings.xml
new file mode 100644
index 0000000..31843f3
--- /dev/null
+++ b/res/values-el/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Ημερομηνία καταγραφής</string>
+</resources>
diff --git a/res/values-el/codeaurora_strings.xml b/res/values-el/codeaurora_strings.xml
new file mode 100644
index 0000000..88f5882
--- /dev/null
+++ b/res/values-el/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Βήμα</string>
+    <string name="step_option_desc">Προσαρμόστε το βήμα fast forward/rewind</string>
+    <string name="setp_option_three_second">3 δευτερόλεπτα</string>
+    <string name="setp_option_six_second">6 δευτερόλεπτα</string>
+    <string name="loop">"Επανάληψη"</string>
+    <string name="single">"Μονό"</string>
+    <string name="stereo">"Στερεοφωνικό"</string>
+    <string name="speaker_on">Ηχείο ενεργό</string>
+    <string name="speaker_off">Ηχείο ανενεργό</string>
+    <string name="speaker_need_headset">Συνδέστε ακουστικά για να χρησιμοποιήσετε αυτή τη δυνατότητα.</string>
+    <string name="single_track">"Μονό κομμάτι"</string>
+    <string name="input_url">"Εισάγετε URL"</string>
+    <string name="streaming_settings">"Ρυθµίσεις ροής"</string>
+    <string name="next">"Επόμενο"</string>
+    <string name="previous">"Προηγούμενο"</string>
+    <string name="buffer_size">Μέγεθος buffer</string>
+    <string name="apn">Προτιμώμενο APN</string>
+    <string name="rtp_min_port">Ελάχιστη θύρα</string>
+    <string name="rtp_max_port">Μέγιστη θύρα</string>
+    <string name="set_rtp_min_port">Ορισμός ελάχιστης θύρας</string>
+    <string name="set_rtp_max_port">Ορισμός μέγιστης θύρας</string>
+    <string name="set_buffer_size">Ορισμός μεγέθους buffer</string>
+    <string name="set_apn">Επιλογή προτιμώμενου APN</string>
+    <string name="setting">Ρυθμίσεις</string>
+    <string name="server_timeout_title">"Χρονικό όριο διακομιστή"</string>
+    <string name="server_timeout_message">"Επανασύνδεση με το διακομιστή για αναπαραγωγή του βίντεο;"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Η σύνδεση απέτυχε, προσπάθεια επανασύνδεσης με το %1$d\u2026"</string>
+    <string name="media_controller_live">Ζωντανά</string>
+    <string name="media_controller_playing">Γίνεται αναπαραγωγή</string>
+    <string name="media_controller_connecting">Σύνδεση\u2026</string>
+    <string name="bookmark_add">"Προσθήκη σελιδοδείκτη"</string>
+    <string name="bookmark_display">"Εμφάνιση σελιδοδεικτών"</string>
+    <string name="bookmark_empty">"Δεν υπάρχουν σελιδοδείκτες"</string>
+    <string name="bookmark_exist">"Ο σελιδοδείκτης υπάρχει ήδη"</string>
+    <string name="bookmark_add_success">"Ο σελιδοδείκτης προστέθηκε"</string>
+    <string name="bookmark_list">"Σελιδοδείκτες"</string>
+    <string name="bookmark_title">"Τίτλος"</string>
+    <string name="bookmark_location">"Τοποθεσία"</string>
+    <string name="delete_all">"Διαγραφή όλων"</string>
+    <string name="default_title">"Προεπιλεγμένος τίτλος"</string>
+    <string name="more_image">Περισσότερες εικόνες</string>
+    <string name="mute_nosupport">Δεν είναι δυνατή η σίγαση: το βίντεο δεν υποστηρίζεται</string>
+    <string name="map_activity_not_found_err">Δεν υπάρχει εγκατεστημένη καμία εφαρμογή χαρτών ώστε να δείτε την τοποθεσία.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d βίντεο</item>
+        <item quantity="other">%1$d βίντεο</item>
+    </plurals>
+    <string name="cannot_share_items">Τα μέγιστα επιλεγμένα στοιχεία για κοινοποίηση είναι 300</string>
+    <string name="share_dialogue_title">Κοινοποίηση μέσω</string>
+    <string name="no_faces">Χωρίς πρόσωπα</string>
+    <string name="fail_trim">Δυστυχώς δεν είναι δυνατή η περικοπή αυτού του αρχείου βίντεο</string>
+    <string name="can_not_trim">Μπορούν να περικοπούν μόνο αρχεία mp4 και 3gp</string>
+    <string name="drm_license_info">Πληροφορίες άδειας DRM</string>
+    <string name="timeline_title">Χρονοδιάγραμμα</string>
+    <string name="albums_title">Άλμπουμ</string>
+    <string name="videos_title">Βίντεο</string>
+    <string name="action_viewtype_list">Προβολή λίστας</string>
+    <string name="tvEmptyAlbum">Δεν βρέθηκαν φωτογραφίες</string>
+    <string name="tvEmptyVideos">Δεν βρέθηκαν βίντεο</string>
+    <string name="text_makeup_whiten">Λεύκανση</string>
+    <string name="text_makeup_Soften">Μαλάκωση</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Κανονικό</string>
+    <string name="truescanner_white">Άσπρος πίνακας</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Αφαίρεση λάμψης</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Η εικόνα που εισάγατε είναι πολύ μικρή για επεξεργαστεί.</string>
+    <string name="seestraight_process_fail">Δεν ήταν δυνατή η επεξεργασία της εικόνας.</string>
+    <string name="trim_video_exit_title">Απόρριψη αλλαγών;</string>
+    <string name="trim_video_exit_msg">Απόρριψη αλλαγών που έγιναν σε αυτό το βίντεο;</string>
+    <string name="trim_video_exit_discard">ΑΠΠΟΡΙΨΗ</string>
+</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 507b210..0a1be14 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -70,17 +70,17 @@
     <string name="switch_to_camera" msgid="7280111806675169992">"Φωτογραφική μηχανή"</string>
   <plurals name="number_of_items_selected">
     <item quantity="zero" msgid="2142579311530586258">"Επιλέχθηκαν %1$d"</item>
-    <item quantity="one" msgid="2478365152745637768">"Επιλέχθηκαν %1$d"</item>
+    <item quantity="one" msgid="2478365152745637768">"Επιλέχθηκε %1$d"</item>
     <item quantity="other" msgid="754722656147810487">"Επιλέχθηκαν %1$d"</item>
   </plurals>
   <plurals name="number_of_albums_selected">
     <item quantity="zero" msgid="749292746814788132">"Επιλέχθηκαν %1$d"</item>
-    <item quantity="one" msgid="6184377003099987825">"Επιλέχθηκαν %1$d"</item>
+    <item quantity="one" msgid="6184377003099987825">"Επιλέχθηκε %1$d"</item>
     <item quantity="other" msgid="53105607141906130">"Επιλέχθηκαν %1$d"</item>
   </plurals>
   <plurals name="number_of_groups_selected">
     <item quantity="zero" msgid="3466388370310869238">"Επιλέχθηκαν %1$d"</item>
-    <item quantity="one" msgid="5030162638216034260">"Επιλέχθηκαν %1$d"</item>
+    <item quantity="one" msgid="5030162638216034260">"Επιλέχθηκε %1$d"</item>
     <item quantity="other" msgid="3512041363942842738">"Επιλέχθηκαν %1$d"</item>
   </plurals>
     <string name="show_on_map" msgid="6157544221201750980">"Εμφάνιση στον χάρτη"</string>
diff --git a/res/values-en-rAU/cm_strings.xml b/res/values-en-rAU/cm_strings.xml
new file mode 100644
index 0000000..6bb240e
--- /dev/null
+++ b/res/values-en-rAU/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Record time</string>
+</resources>
diff --git a/res/values-en-rAU/codeaurora_strings.xml b/res/values-en-rAU/codeaurora_strings.xml
new file mode 100644
index 0000000..ad8f80a
--- /dev/null
+++ b/res/values-en-rAU/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Step</string>
+    <string name="step_option_desc">Customise fast forward/rewind step</string>
+    <string name="setp_option_three_second">3 seconds</string>
+    <string name="setp_option_six_second">6 seconds</string>
+    <string name="loop">"Loop"</string>
+    <string name="single">"Single"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker ON</string>
+    <string name="speaker_off">Speaker OFF</string>
+    <string name="speaker_need_headset">Plug in headphones to use this feature.</string>
+    <string name="single_track">"Single track"</string>
+    <string name="input_url">"Enter URL"</string>
+    <string name="streaming_settings">"Streaming settings"</string>
+    <string name="next">"Next"</string>
+    <string name="previous">"Previous"</string>
+    <string name="buffer_size">Buffer size</string>
+    <string name="apn">Preferred APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Set min port</string>
+    <string name="set_rtp_max_port">Set max port</string>
+    <string name="set_buffer_size">Set buffer size</string>
+    <string name="set_apn">Select preferred APN</string>
+    <string name="setting">Settings</string>
+    <string name="server_timeout_title">"Server timeout"</string>
+    <string name="server_timeout_message">"Reconnect to the server to play the video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connection failed, trying to reconnect to %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Playing</string>
+    <string name="media_controller_connecting">Connecting\u2026</string>
+    <string name="bookmark_add">"Add bookmark"</string>
+    <string name="bookmark_display">"Show bookmarks"</string>
+    <string name="bookmark_empty">"No bookmarks"</string>
+    <string name="bookmark_exist">"Bookmark already exists"</string>
+    <string name="bookmark_add_success">"Bookmark added"</string>
+    <string name="bookmark_list">"Bookmarks"</string>
+    <string name="bookmark_title">"Title"</string>
+    <string name="bookmark_location">"Location"</string>
+    <string name="delete_all">"Delete all"</string>
+    <string name="default_title">"Default title"</string>
+    <string name="more_image">More images</string>
+    <string name="mute_nosupport">Can not mute : video not supported</string>
+    <string name="map_activity_not_found_err">There is no maps app installed to show the location.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+    <string name="cannot_share_items">Max selected items for share is 300</string>
+    <string name="share_dialogue_title">Share via</string>
+    <string name="no_faces">No faces</string>
+    <string name="fail_trim">Sorry, this video file can not be trimmed</string>
+    <string name="can_not_trim">Only mp4 and 3gp files can be trimmed</string>
+    <string name="drm_license_info">DRM licence info</string>
+    <string name="timeline_title">Timeline</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">List view</string>
+    <string name="tvEmptyAlbum">No photos found</string>
+    <string name="tvEmptyVideos">No videos found</string>
+    <string name="text_makeup_whiten">Whiten</string>
+    <string name="text_makeup_Soften">Soften</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Input image is too small to process.</string>
+    <string name="seestraight_process_fail">Couldn\'t process the image.</string>
+    <string name="trim_video_exit_title">Discard changes?</string>
+    <string name="trim_video_exit_msg">Discard the changes made to this video?</string>
+    <string name="trim_video_exit_discard">DISCARD</string>
+</resources>
diff --git a/res/values-en-rCA/cm_strings.xml b/res/values-en-rCA/cm_strings.xml
new file mode 100644
index 0000000..6bb240e
--- /dev/null
+++ b/res/values-en-rCA/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Record time</string>
+</resources>
diff --git a/res/values-en-rCA/codeaurora_strings.xml b/res/values-en-rCA/codeaurora_strings.xml
new file mode 100644
index 0000000..c1df96f
--- /dev/null
+++ b/res/values-en-rCA/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Step</string>
+    <string name="step_option_desc">Customize fast forward/rewind step</string>
+    <string name="setp_option_three_second">3 seconds</string>
+    <string name="setp_option_six_second">6 seconds</string>
+    <string name="loop">"Loop"</string>
+    <string name="single">"Single"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker ON</string>
+    <string name="speaker_off">Speaker OFF</string>
+    <string name="speaker_need_headset">Plug in headphones to use this feature.</string>
+    <string name="single_track">"Single track"</string>
+    <string name="input_url">"Enter URL"</string>
+    <string name="streaming_settings">"Streaming settings"</string>
+    <string name="next">"Next"</string>
+    <string name="previous">"Previous"</string>
+    <string name="buffer_size">Buffer size</string>
+    <string name="apn">Preferred APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Set min port</string>
+    <string name="set_rtp_max_port">Set max port</string>
+    <string name="set_buffer_size">Set buffer size</string>
+    <string name="set_apn">Select preferred APN</string>
+    <string name="setting">Settings</string>
+    <string name="server_timeout_title">"Server timeout"</string>
+    <string name="server_timeout_message">"Reconnect to the server to play the video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connection failed, trying to reconnect to %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Playing</string>
+    <string name="media_controller_connecting">Connecting\u2026</string>
+    <string name="bookmark_add">"Add bookmark"</string>
+    <string name="bookmark_display">"Show bookmarks"</string>
+    <string name="bookmark_empty">"No bookmarks"</string>
+    <string name="bookmark_exist">"Bookmark already exists"</string>
+    <string name="bookmark_add_success">"Bookmark added"</string>
+    <string name="bookmark_list">"Bookmarks"</string>
+    <string name="bookmark_title">"Title"</string>
+    <string name="bookmark_location">"Location"</string>
+    <string name="delete_all">"Delete all"</string>
+    <string name="default_title">"Default title"</string>
+    <string name="more_image">More images</string>
+    <string name="mute_nosupport">Cannot mute : video not supported</string>
+    <string name="map_activity_not_found_err">There is no maps app installed to show the location.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+    <string name="cannot_share_items">Max selected items for share is 300</string>
+    <string name="share_dialogue_title">Share via</string>
+    <string name="no_faces">No faces</string>
+    <string name="fail_trim">Sorry, this video file can not be trimmed</string>
+    <string name="can_not_trim">Only mp4 and 3gp files can be trimmed</string>
+    <string name="drm_license_info">DRM license info</string>
+    <string name="timeline_title">Timeline</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">List view</string>
+    <string name="tvEmptyAlbum">No photos found</string>
+    <string name="tvEmptyVideos">No videos found</string>
+    <string name="text_makeup_whiten">Whiten</string>
+    <string name="text_makeup_Soften">Soften</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Input image is too small to process.</string>
+    <string name="seestraight_process_fail">Couldn\'t process the image.</string>
+    <string name="trim_video_exit_title">Discard changes?</string>
+    <string name="trim_video_exit_msg">Discard the changes made to this video?</string>
+    <string name="trim_video_exit_discard">DISCARD</string>
+</resources>
diff --git a/res/values-en-rCA/filtershow_strings.xml b/res/values-en-rCA/filtershow_strings.xml
deleted file mode 100644
index bd076f4..0000000
--- a/res/values-en-rCA/filtershow_strings.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--  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.
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="title_activity_filter_show" msgid="2036539130684382763">"Photo Editor"</string>
-    <string name="cannot_load_image" msgid="5023634941212959976">"Cannot load the image!"</string>
-    <string name="cannot_edit_original" msgid="5890293845882609388">"Cannot edit original"</string>
-    <!-- no translation found for original_picture_text (3076213290079909698) -->
-    <skip />
-    <string name="setting_wallpaper" msgid="4679087092300036632">"Setting wallpaper"</string>
-    <string name="download_failure" msgid="5923323939788582895">"Could not download photo. Network unavailable."</string>
-    <string name="original" msgid="3524493791230430897">"Original"</string>
-    <string name="borders" msgid="2067345080568684614">"Borders"</string>
-    <string name="custom_border" msgid="8679893731790931871">"Customise"</string>
-    <string name="filtershow_undo" msgid="6781743189243585101">"Undo"</string>
-    <string name="filtershow_redo" msgid="4219489910543059747">"Redo"</string>
-    <string name="show_imagestate_panel" msgid="281932769701043015">"Show Applied Effects"</string>
-    <string name="hide_imagestate_panel" msgid="7207643485811695257">"Hide Applied Effects"</string>
-    <string name="export_image" msgid="3202835713172222134">"Export"</string>
-    <string name="print_image" msgid="1942989216591621413">"Print"</string>
-    <string name="export_flattened" msgid="9046192331465915411">"Export Flattened Image"</string>
-    <string name="select_output_settings" msgid="1268532018080310748">"The exported image will be a copy, without the history."</string>
-    <string name="quality" msgid="179292110309050529">"Quality"</string>
-    <string name="size" msgid="4639404642236356037">"Size"</string>
-    <string name="x" msgid="6810256999024563662">"x"</string>
-    <string name="menu_settings" msgid="6428291655769260831">"Settings"</string>
-    <string name="unsaved" msgid="8704442449002374375">"There are unsaved changes to this image."</string>
-    <string name="save_before_exit" msgid="2680660633675916712">"Do you want to save before exiting?"</string>
-    <string name="save_and_exit" msgid="3628425023766687419">"Save and Exit"</string>
-    <string name="save_and_processing" msgid="6371565035837463194">"Processing full resolution image..."</string>
-    <string name="exit" msgid="242642957038770113">"Exit"</string>
-    <string name="history" msgid="455767361472692409">"History"</string>
-    <string name="reset" msgid="9013181350779592937">"Reset"</string>
-    <!-- no translation found for history_original (150973253194312841) -->
-    <skip />
-    <string name="imageState" msgid="8632586742752891968">"Applied Effects"</string>
-    <string name="compare_original" msgid="8140838959007796977">"Compare"</string>
-    <string name="apply_effect" msgid="1218288221200568947">"Apply"</string>
-    <string name="reset_effect" msgid="7712605581024929564">"Reset"</string>
-    <string name="aspect" msgid="4025244950820813059">"Aspect"</string>
-    <string name="aspect1to1_effect" msgid="1159104543795779123">"1, 1"</string>
-    <string name="aspect4to3_effect" msgid="7968067847241223578">"4:3"</string>
-    <string name="aspect3to4_effect" msgid="7078163990979248864">"3:4"</string>
-    <string name="aspect4to6_effect" msgid="1410129351686165654">"4:6"</string>
-    <string name="aspect5to7_effect" msgid="5122395569059384741">"5:7"</string>
-    <string name="aspect7to5_effect" msgid="5780001758108328143">"7:5"</string>
-    <string name="aspect9to16_effect" msgid="7740468012919660728">"16:9"</string>
-    <string name="aspectNone_effect" msgid="6263330561046574134">"None"</string>
-    <!-- no translation found for aspectOriginal_effect (5678516555493036594) -->
-    <skip />
-    <string name="Fixed" msgid="8017376448916924565">"Fixed"</string>
-    <string name="tinyplanet" msgid="2783694326474415761">"Tiny Planet"</string>
-    <string name="exposure" msgid="6526397045949374905">"Exposure"</string>
-    <string name="sharpness" msgid="6463103068318055412">"Sharpness"</string>
-    <string name="contrast" msgid="2310908487756769019">"Contrast"</string>
-    <string name="vibrance" msgid="3326744578577835915">"Vibrancy"</string>
-    <string name="saturation" msgid="7026791551032438585">"Saturation"</string>
-    <string name="bwfilter" msgid="8927492494576933793">"BW Filter"</string>
-    <string name="wbalance" msgid="6346581563387083613">"Autocolour"</string>
-    <string name="hue" msgid="6231252147971086030">"Hue"</string>
-    <string name="shadow_recovery" msgid="3928572915300287152">"Shadows"</string>
-    <string name="highlight_recovery" msgid="8262208470735204243">"Highlights"</string>
-    <string name="curvesRGB" msgid="915010781090477550">"Curves"</string>
-    <string name="vignette" msgid="934721068851885390">"Vignette"</string>
-    <string name="vignette_main" msgid="6046495605390665423">"Vignette"</string>
-    <string name="vignette_exposure" msgid="6862058227309534094">"Exposure"</string>
-    <string name="vignette_saturation" msgid="1617055207565719771">"Saturation"</string>
-    <string name="vignette_contrast" msgid="955732121756799897">"Contrast"</string>
-    <string name="vignette_falloff" msgid="690918055030064199">"Falloff"</string>
-    <string name="redeye" msgid="4508883127049472069">"Red Eye"</string>
-    <string name="imageDraw" msgid="6918552177844486656">"Draw"</string>
-    <string name="straighten" msgid="26025591664983528">"Straighten"</string>
-    <string name="crop" msgid="5781263790107850771">"Crop"</string>
-    <string name="rotate" msgid="2796802553793795371">"Rotate"</string>
-    <string name="mirror" msgid="5482518108154883096">"Mirror"</string>
-    <string name="negative" msgid="6998313764388022201">"Negative"</string>
-    <string name="none" msgid="6633966646410296520">"None"</string>
-    <string name="edge" msgid="7036064886242147551">"Edges"</string>
-    <string name="kmeans" msgid="2080952022674981541">"Posterise"</string>
-    <string name="downsample" msgid="3552938534146980104">"Downsample"</string>
-    <string name="grad" msgid="546774853424848655">"Graduated"</string>
-    <string name="editor_grad_brightness" msgid="5937316734380235741">"Brightness"</string>
-    <string name="editor_grad_contrast" msgid="3454456673401803360">"Contrast"</string>
-    <string name="editor_grad_saturation" msgid="3760247354109521726">"Saturation"</string>
-    <string name="editor_chan_sat_main" msgid="4427652337797121940">"Main"</string>
-    <string name="editor_chan_sat_red" msgid="1699222266490540696">"Red"</string>
-    <string name="editor_chan_sat_yellow" msgid="1488997071882154179">"Yellow"</string>
-    <string name="editor_chan_sat_green" msgid="1514055896212975167">"Green"</string>
-    <string name="editor_chan_sat_cyan" msgid="1367634650172508288">"Cyan"</string>
-    <string name="editor_chan_sat_blue" msgid="384409736863387895">"Blue"</string>
-    <string name="editor_chan_sat_magenta" msgid="6689215719351415546">"Magenta"</string>
-    <string name="editor_grad_style" msgid="2168414479007745179">"Style"</string>
-    <string name="editor_grad_new" msgid="4857265951369377379">"new"</string>
-    <string name="curves_channel_rgb" msgid="7909209509638333690">"RGB"</string>
-    <string name="curves_channel_red" msgid="4199710104162111357">"Red"</string>
-    <string name="curves_channel_green" msgid="3733003466905031016">"Green"</string>
-    <string name="curves_channel_blue" msgid="9129211507395079371">"Blue"</string>
-    <string name="draw_style" msgid="2036125061987325389">"Style"</string>
-    <string name="draw_size" msgid="4360005386104151209">"Size"</string>
-    <string name="draw_hue" msgid="4975135843189267133">"Hue"</string>
-    <string name="draw_saturation" msgid="5394395648014454882">"Saturation"</string>
-    <string name="draw_value" msgid="6571604055161538273">"Brightness"</string>
-    <string name="draw_color" msgid="2119030386987211193">"Colour"</string>
-    <string name="draw_style_line" msgid="9216476853904429628">"Lines"</string>
-    <string name="draw_style_brush_spatter" msgid="7612691122932981554">"Marker"</string>
-    <string name="draw_style_brush_marker" msgid="8468302322165644292">"Spatter"</string>
-    <string name="draw_clear" msgid="6728155515454921052">"Clear"</string>
-    <string name="color_border_size" msgid="1086895807615869290">"Thickness"</string>
-    <string name="color_border_corner_size" msgid="7637235159438869979">"Corner Size"</string>
-    <string name="color_border_color" msgid="8765458414425980711">"Colour"</string>
-    <string name="color_border_clear" msgid="4418261191091091722">"Clear"</string>
-    <string name="color_pick_select" msgid="734312818059057394">"Choose custom colour"</string>
-    <string name="color_pick_title" msgid="6195567431995308876">"Select Colour"</string>
-    <string name="draw_size_title" msgid="3121649039610273977">"Select Size"</string>
-    <string name="draw_size_accept" msgid="6781529716526190028">"OK"</string>
-    <string name="state_panel_original" msgid="9069584409934164419">"Original"</string>
-    <string name="state_panel_result" msgid="318640531123298676">"Result"</string>
-    <string name="filtershow_notification_label" msgid="1653168445525855247">"Saving Image"</string>
-    <string name="filtershow_notification_message" msgid="2661871765484036286">"Processing..."</string>
-    <string name="filtershow_save_preset" msgid="3933550455577927439">"Save current preset"</string>
-    <string name="filtershow_manage_preset" msgid="3872896753708921286">"Manage user presets"</string>
-    <string name="filtershow_new_preset" msgid="8923930134923416617">"New Preset"</string>
-    <string name="filtershow_preset_name" msgid="7015939727047649866">"Preset Name"</string>
-    <string name="filtershow_show_info_panel" msgid="5773036746043711115">"Information"</string>
-    <string name="filtershow_show_info_panel_name" msgid="5908258517140549439">"Image Name"</string>
-    <string name="filtershow_show_info_panel_size" msgid="1714666849204493017">"Image Size"</string>
-    <string name="filtershow_show_info_panel_histogram" msgid="2669188469897955809">"Histogram"</string>
-    <string name="filtershow_show_info_panel_exif" msgid="4965486882625125154">"EXIF Data"</string>
-    <string name="filtershow_add_button_looks" msgid="8630823661416925426">"Preset"</string>
-    <string name="filtershow_add_button_versions" msgid="7620107266685809612">"Version"</string>
-    <string name="filtershow_version_original" msgid="1413894292200912828">"Original"</string>
-    <string name="filtershow_version_current" msgid="6609334422797468952">"Current"</string>
-    <string name="filtershow_exif_model" msgid="3543206476046267466">"Model"</string>
-    <string name="filtershow_exif_aperture" msgid="5076571522763604380">"Aperture"</string>
-    <string name="filtershow_exif_focal_length" msgid="5925151469731623706">"Focal Length"</string>
-    <string name="filtershow_exif_iso" msgid="5822494416955625317">"ISO"</string>
-    <string name="filtershow_exif_subject_distance" msgid="4920632253433906646">"Subject Distance"</string>
-    <string name="filtershow_exif_date" msgid="8882402253732028544">"Date taken"</string>
-    <string name="filtershow_exif_f_stop" msgid="6081797865604483139">"F Stop"</string>
-    <string name="filtershow_exif_exposure_time" msgid="4099067062781294115">"Exposure Time"</string>
-    <string name="filtershow_exif_copyright" msgid="8801875918803737581">"Copyright"</string>
-</resources>
diff --git a/res/values-en-rGB/cm_strings.xml b/res/values-en-rGB/cm_strings.xml
new file mode 100644
index 0000000..6bb240e
--- /dev/null
+++ b/res/values-en-rGB/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Record time</string>
+</resources>
diff --git a/res/values-en-rGB/codeaurora_strings.xml b/res/values-en-rGB/codeaurora_strings.xml
new file mode 100644
index 0000000..d61f1e6
--- /dev/null
+++ b/res/values-en-rGB/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Step</string>
+    <string name="step_option_desc">Customize fast forward/rewind step</string>
+    <string name="setp_option_three_second">3 seconds</string>
+    <string name="setp_option_six_second">6 seconds</string>
+    <string name="loop">"Loop"</string>
+    <string name="single">"Single"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker ON</string>
+    <string name="speaker_off">Speaker OFF</string>
+    <string name="speaker_need_headset">Plug in headphones to use this feature.</string>
+    <string name="single_track">"Single track"</string>
+    <string name="input_url">"Enter URL"</string>
+    <string name="streaming_settings">"Streaming settings"</string>
+    <string name="next">"Next"</string>
+    <string name="previous">"Previous"</string>
+    <string name="buffer_size">Buffer size</string>
+    <string name="apn">Preferred APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Set min port</string>
+    <string name="set_rtp_max_port">Set max port</string>
+    <string name="set_buffer_size">Set buffer size</string>
+    <string name="set_apn">Select preferred APN</string>
+    <string name="setting">Settings</string>
+    <string name="server_timeout_title">"Server timeout"</string>
+    <string name="server_timeout_message">"Reconnect to the server to play the video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connection failed, trying to reconnect to %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Playing</string>
+    <string name="media_controller_connecting">Connecting\u2026</string>
+    <string name="bookmark_add">"Add bookmark"</string>
+    <string name="bookmark_display">"Show bookmarks"</string>
+    <string name="bookmark_empty">"No bookmarks"</string>
+    <string name="bookmark_exist">"Bookmark already exists"</string>
+    <string name="bookmark_add_success">"Bookmark added"</string>
+    <string name="bookmark_list">"Bookmarks"</string>
+    <string name="bookmark_title">"Title"</string>
+    <string name="bookmark_location">"Location"</string>
+    <string name="delete_all">"Delete all"</string>
+    <string name="default_title">"Default title"</string>
+    <string name="more_image">More images</string>
+    <string name="mute_nosupport">Cannot mute : video not supported</string>
+    <string name="map_activity_not_found_err">There is no maps app installed to show the location.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+    <string name="cannot_share_items">Max selected items for share is 300</string>
+    <string name="share_dialogue_title">Share via</string>
+    <string name="no_faces">No faces</string>
+    <string name="fail_trim">Sorry, this video file can not be trimmed</string>
+    <string name="can_not_trim">Only mp4 and 3gp files can be trimmed</string>
+    <string name="drm_license_info">DRM licence info</string>
+    <string name="timeline_title">Timeline</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">List view</string>
+    <string name="tvEmptyAlbum">No photos found</string>
+    <string name="tvEmptyVideos">No videos found</string>
+    <string name="text_makeup_whiten">Whiten</string>
+    <string name="text_makeup_Soften">Soften</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Input image is too small to process.</string>
+    <string name="seestraight_process_fail">Couldn\'t process the image.</string>
+    <string name="trim_video_exit_title">Discard changes?</string>
+    <string name="trim_video_exit_msg">Discard the changes made to this video?</string>
+    <string name="trim_video_exit_discard">DISCARD</string>
+</resources>
diff --git a/res/values-en-rIN/cm_strings.xml b/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 0000000..6bb240e
--- /dev/null
+++ b/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Record time</string>
+</resources>
diff --git a/res/values-en-rIN/codeaurora_strings.xml b/res/values-en-rIN/codeaurora_strings.xml
new file mode 100644
index 0000000..b91e033
--- /dev/null
+++ b/res/values-en-rIN/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Step</string>
+    <string name="step_option_desc">Customise fast forward/rewind step</string>
+    <string name="setp_option_three_second">3 seconds</string>
+    <string name="setp_option_six_second">6 seconds</string>
+    <string name="loop">"Loop"</string>
+    <string name="single">"Single"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker ON</string>
+    <string name="speaker_off">Speaker OFF</string>
+    <string name="speaker_need_headset">Plug in headphones to use this feature.</string>
+    <string name="single_track">"Single track"</string>
+    <string name="input_url">"Enter URL"</string>
+    <string name="streaming_settings">"Streaming settings"</string>
+    <string name="next">"Next"</string>
+    <string name="previous">"Previous"</string>
+    <string name="buffer_size">Buffer size</string>
+    <string name="apn">Preferred APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Set min port</string>
+    <string name="set_rtp_max_port">Set max port</string>
+    <string name="set_buffer_size">Set buffer size</string>
+    <string name="set_apn">Select preferred APN</string>
+    <string name="setting">Settings</string>
+    <string name="server_timeout_title">"Server timeout"</string>
+    <string name="server_timeout_message">"Reconnect to the server to play the video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connection failed, trying to reconnect to %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Playing</string>
+    <string name="media_controller_connecting">Connecting\u2026</string>
+    <string name="bookmark_add">"Add bookmark"</string>
+    <string name="bookmark_display">"Show bookmarks"</string>
+    <string name="bookmark_empty">"No bookmarks"</string>
+    <string name="bookmark_exist">"Bookmark already exists"</string>
+    <string name="bookmark_add_success">"Bookmark added"</string>
+    <string name="bookmark_list">"Bookmarks"</string>
+    <string name="bookmark_title">"Title"</string>
+    <string name="bookmark_location">"Location"</string>
+    <string name="delete_all">"Delete all"</string>
+    <string name="default_title">"Default title"</string>
+    <string name="more_image">More images</string>
+    <string name="mute_nosupport">Can not mute : video not supported</string>
+    <string name="map_activity_not_found_err">There is no maps app installed to show the location.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+    <string name="cannot_share_items">Max selected items for share is 300</string>
+    <string name="share_dialogue_title">Share via</string>
+    <string name="no_faces">No faces</string>
+    <string name="fail_trim">Sorry, this video file can not be trimmed</string>
+    <string name="can_not_trim">Only mp4 and 3gp files can be trimmed</string>
+    <string name="drm_license_info">DRM license info</string>
+    <string name="timeline_title">Timeline</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">List view</string>
+    <string name="tvEmptyAlbum">No photos found</string>
+    <string name="tvEmptyVideos">No videos found</string>
+    <string name="text_makeup_whiten">Whiten</string>
+    <string name="text_makeup_Soften">Soften</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Input image is too small to process.</string>
+    <string name="seestraight_process_fail">Couldn\'t process the image.</string>
+    <string name="trim_video_exit_title">Discard changes?</string>
+    <string name="trim_video_exit_msg">Discard the changes made to this video?</string>
+    <string name="trim_video_exit_discard">DISCARD</string>
+</resources>
diff --git a/res/values-eo/codeaurora_strings.xml b/res/values-eo/codeaurora_strings.xml
new file mode 100644
index 0000000..d053f36
--- /dev/null
+++ b/res/values-eo/codeaurora_strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_three_second">3 sekundoj</string>
+    <string name="setp_option_six_second">6 sekundoj</string>
+    <string name="bookmark_add">"Aldoni legosignon"</string>
+    <string name="bookmark_list">"Legosignoj"</string>
+    <string name="bookmark_location">"Loko"</string>
+</resources>
diff --git a/res/values-eo/filtershow_strings.xml b/res/values-eo/filtershow_strings.xml
new file mode 100644
index 0000000..bafe961
--- /dev/null
+++ b/res/values-eo/filtershow_strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="custom_border">Propra</string>
+    <string name="export_image">Elporti</string>
+    <string name="print_image">Presi</string>
+    <string name="menu_settings">Agordoj</string>
+    <string name="history">Historio</string>
+    <string name="editor_grad_style">Stilo</string>
+    <string name="editor_grad_new">nova</string>
+    <string name="filtershow_add_button_versions">Versio</string>
+</resources>
diff --git a/res/values-eo/strings.xml b/res/values-eo/strings.xml
new file mode 100644
index 0000000..8651322
--- /dev/null
+++ b/res/values-eo/strings.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="delete">Forigi</string>
+    <string name="cancel">Nuligi</string>
+    <string name="share">Konigi</string>
+    <string name="deleted">Forigita</string>
+    <string name="close">Fermi</string>
+    <string name="edit">Redakti</string>
+    <string name="title">Titolo</string>
+    <string name="description">Priskribo</string>
+    <string name="location">Loko</string>
+    <string name="unknown">Nekonata</string>
+    <string name="Import">Enporti</string>
+    <string name="locations">Lokoj</string>
+    <string name="settings">Agordoj</string>
+    <string name="folder_download">Elŝuti</string>
+    <string name="folder_screenshot">Ekrankopio</string>
+    <string name="save" msgid="8140440041190264400">Konservi</string>
+    <string name="pref_camera_location_label">LOKO</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="one">1 sekundo</item>
+        <item quantity="other">%d sekundoj</item>
+    </plurals>
+    <string name="pref_camera_scenemode_entry_night">Nokto</string>
+    <string name="pref_camera_scenemode_label_night">NOKTO</string>
+    <string name="pref_camera_countdown_label_one">1 SEKUNDO</string>
+    <string name="pref_camera_countdown_label_three">3 SEKUNDOJ</string>
+    <string name="pref_camera_countdown_label_ten">10 SEKUNDOJ</string>
+    <string name="pref_camera_countdown_label_fifteen">15 SEKUNDOJ</string>
+    <string name="pref_video_time_lapse_frame_interval_500">0,5 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 sekundo</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">1,5 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2,5 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 sekundoj</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">0,5 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">1 minuto</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">1,5 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2,5 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 minutoj</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">0,5 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 horo</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2,5 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 horoj</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 horoj</string>
+    <string name="time_lapse_seconds">sekundoj</string>
+    <string name="time_lapse_minutes">minutoj</string>
+    <string name="time_lapse_hours">horoj</string>
+    <string name="remember_location_yes">Jes</string>
+    <string name="menu_search">Serĉi</string>
+    <string name="camera_menu_settings_label">AGORDOJ</string>
+</resources>
diff --git a/res/values-es-rUS/cm_strings.xml b/res/values-es-rUS/cm_strings.xml
new file mode 100644
index 0000000..65e870b
--- /dev/null
+++ b/res/values-es-rUS/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Fecha de grabación</string>
+</resources>
diff --git a/res/values-es-rUS/codeaurora_strings.xml b/res/values-es-rUS/codeaurora_strings.xml
new file mode 100644
index 0000000..8e2111c
--- /dev/null
+++ b/res/values-es-rUS/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Salto</string>
+    <string name="step_option_desc">Personaliza el salto rápido hacia adelante o atrás</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Bucle"</string>
+    <string name="single">"Sencillo"</string>
+    <string name="stereo">"Estéreo"</string>
+    <string name="speaker_on">Altavoz encendido</string>
+    <string name="speaker_off">Altavoz apagado</string>
+    <string name="speaker_need_headset">Conecta los auriculares para usar esta característica.</string>
+    <string name="single_track">"Pista sencilla"</string>
+    <string name="input_url">"Ingresar URL"</string>
+    <string name="streaming_settings">"Ajustes de transmisión"</string>
+    <string name="next">"Siguiente"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamaño de búfer</string>
+    <string name="apn">APN preferido</string>
+    <string name="rtp_min_port">Puerto inferior</string>
+    <string name="rtp_max_port">Puerto superior</string>
+    <string name="set_rtp_min_port">Establecer puerto inferior</string>
+    <string name="set_rtp_max_port">Establecer puerto superior</string>
+    <string name="set_buffer_size">Establecer tamaño de búfer</string>
+    <string name="set_apn">Seleccionar APN preferido</string>
+    <string name="setting">Ajustes</string>
+    <string name="server_timeout_title">"Tiempo de espera del servidor"</string>
+    <string name="server_timeout_message">"¿Volver a conectar al servidor para reproducir el video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Error de conexión, intentando volver a conectar con %1$d\u2026"</string>
+    <string name="media_controller_live">En vivo</string>
+    <string name="media_controller_playing">Reproduciendo</string>
+    <string name="media_controller_connecting">Conectando\u2026</string>
+    <string name="bookmark_add">"Añadir marcador"</string>
+    <string name="bookmark_display">"Mostrar marcadores"</string>
+    <string name="bookmark_empty">"Sin marcadores"</string>
+    <string name="bookmark_exist">"El marcador ya existe"</string>
+    <string name="bookmark_add_success">"Marcador añadido"</string>
+    <string name="bookmark_list">"Marcadores"</string>
+    <string name="bookmark_title">"Título"</string>
+    <string name="bookmark_location">"Ubicación"</string>
+    <string name="delete_all">"Borrar todos"</string>
+    <string name="default_title">"Título predefinido"</string>
+    <string name="more_image">Más imágenes</string>
+    <string name="mute_nosupport">No se puede silenciar: video no compatible</string>
+    <string name="map_activity_not_found_err">Sin aplicación de mapas instalada para mostrar la ubicación.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+    <string name="cannot_share_items">El máximo de elementos seleccionados para compartir es de 300</string>
+    <string name="share_dialogue_title">Compartir usando</string>
+    <string name="no_faces">Sin rostros</string>
+    <string name="fail_trim">Lo sentimos, no se puede recortar este video</string>
+    <string name="can_not_trim">Sólo los archivos mp4 y 3gp se pueden recortar</string>
+    <string name="drm_license_info">Información de la licencia DRM</string>
+    <string name="timeline_title">Línea de tiempo</string>
+    <string name="albums_title">Álbumes</string>
+    <string name="videos_title">Videos</string>
+    <string name="action_viewtype_list">Vista de lista</string>
+    <string name="tvEmptyAlbum">No se encontraron imágenes</string>
+    <string name="tvEmptyVideos">No se encontraron videos</string>
+    <string name="text_makeup_whiten">Blanquear</string>
+    <string name="text_makeup_Soften">Suavizar</string>
+    <string name="text_makeup_trimface">Retoque facial</string>
+    <string name="text_makeup_bigeye">Ojos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Pizarra blanca</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Quitar reflejos</string>
+    <string name="hazebuster_acts">Anti bruma</string>
+    <string name="seestraight_acts">Ver directamente</string>
+    <string name="seestraight_input_image_is_small">Imagen ingresada demasiada pequeña para procesarla.</string>
+    <string name="seestraight_process_fail">No se pudo procesar la imagen.</string>
+    <string name="trim_video_exit_title">¿Descartar cambios?</string>
+    <string name="trim_video_exit_msg">¿Descartar los cambios realizados en este video?</string>
+    <string name="trim_video_exit_discard">DESCARTAR</string>
+</resources>
diff --git a/res/values-es/cm_strings.xml b/res/values-es/cm_strings.xml
new file mode 100644
index 0000000..441f7e6
--- /dev/null
+++ b/res/values-es/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Hora de grabación</string>
+</resources>
diff --git a/res/values-es/codeaurora_strings.xml b/res/values-es/codeaurora_strings.xml
new file mode 100644
index 0000000..d6483e4
--- /dev/null
+++ b/res/values-es/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Paso</string>
+    <string name="step_option_desc">Personalizar el salto rápido hacia adelante o hacia atrás</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Bucle"</string>
+    <string name="single">"Simple"</string>
+    <string name="stereo">"Estéreo"</string>
+    <string name="speaker_on">Altavoz encendido</string>
+    <string name="speaker_off">Altavoz apagado</string>
+    <string name="speaker_need_headset">Conecta unos auriculares para usar esta característica.</string>
+    <string name="single_track">"Pista sencilla"</string>
+    <string name="input_url">"Introducir URL"</string>
+    <string name="streaming_settings">"Ajustes de transmisión"</string>
+    <string name="next">"Siguiente"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamaño de memoria intermedia</string>
+    <string name="apn">APN preferido</string>
+    <string name="rtp_min_port">Puerto mínimo</string>
+    <string name="rtp_max_port">Puerto máximo</string>
+    <string name="set_rtp_min_port">Establecer puerto inferior</string>
+    <string name="set_rtp_max_port">Establecer puerto superior</string>
+    <string name="set_buffer_size">Establecer tamaño de memoria intermedia</string>
+    <string name="set_apn">Seleccionar APN preferido</string>
+    <string name="setting">Ajustes</string>
+    <string name="server_timeout_title">"Tiempo de espera del servidor"</string>
+    <string name="server_timeout_message">"¿Volver a conectar al servidor para reproducir el vídeo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Falló la conexión. Intentando volver a conectar con %1$d\u2026"</string>
+    <string name="media_controller_live">En directo</string>
+    <string name="media_controller_playing">Reproduciendo</string>
+    <string name="media_controller_connecting">Conectando\u2026</string>
+    <string name="bookmark_add">"Añadir marcador"</string>
+    <string name="bookmark_display">"Mostrar marcadores"</string>
+    <string name="bookmark_empty">"No hay marcadores"</string>
+    <string name="bookmark_exist">"Este marcador ya existe"</string>
+    <string name="bookmark_add_success">"Marcador añadido"</string>
+    <string name="bookmark_list">"Marcadores"</string>
+    <string name="bookmark_title">"Título"</string>
+    <string name="bookmark_location">"Ubicación"</string>
+    <string name="delete_all">"Eliminar todo"</string>
+    <string name="default_title">"Título por defecto"</string>
+    <string name="more_image">Más imágenes</string>
+    <string name="mute_nosupport">No se puede silenciar: vídeo no soportado</string>
+    <string name="map_activity_not_found_err">No hay ninguna aplicación de mapas instalada para mostrar la ubicación.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vídeo</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">La cantidad máxima de elementos seleccionados para compartir es 300</string>
+    <string name="share_dialogue_title">Compartir vía</string>
+    <string name="no_faces">Sin caras</string>
+    <string name="fail_trim">Este vídeo no puede ser recortado</string>
+    <string name="can_not_trim">Sólo pueden recortarse archivos mp4 y 3gp</string>
+    <string name="drm_license_info">Información de la licencia DRM</string>
+    <string name="timeline_title">Linea de tiempo</string>
+    <string name="albums_title">Álbumes</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Vista de lista</string>
+    <string name="tvEmptyAlbum">No se encontraron fotos</string>
+    <string name="tvEmptyVideos">No se encontraron vídeos</string>
+    <string name="text_makeup_whiten">Blanquear</string>
+    <string name="text_makeup_Soften">Suavizado</string>
+    <string name="text_makeup_trimface">Retoque facial</string>
+    <string name="text_makeup_bigeye">Ojos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Pizarra blanca</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Eliminar reflejos</string>
+    <string name="hazebuster_acts">Anti bruma</string>
+    <string name="seestraight_acts">Ver directamente</string>
+    <string name="seestraight_input_image_is_small">La imagen de entrada es demasiado pequeña para procesar.</string>
+    <string name="seestraight_process_fail">No se pudo procesar la imagen.</string>
+    <string name="trim_video_exit_title">¿Descartar cambios?</string>
+    <string name="trim_video_exit_msg">¿Descartar cambios realizados en este vídeo?</string>
+    <string name="trim_video_exit_discard">DESCARTAR</string>
+</resources>
diff --git a/res/values-et/cm_strings.xml b/res/values-et/cm_strings.xml
new file mode 100644
index 0000000..698b43b
--- /dev/null
+++ b/res/values-et/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Salvestusaeg</string>
+</resources>
diff --git a/res/values-et/codeaurora_strings.xml b/res/values-et/codeaurora_strings.xml
new file mode 100644
index 0000000..205f1a2
--- /dev/null
+++ b/res/values-et/codeaurora_strings.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Samm</string>
+    <string name="step_option_desc">Kohanda kiirkerimise edasi/tagasi sammu</string>
+    <string name="setp_option_three_second">3 sekundit</string>
+    <string name="setp_option_six_second">6 sekundit</string>
+    <string name="loop">"Kordamine"</string>
+    <string name="single">"Üksik"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Kõlar sees</string>
+    <string name="speaker_off">Kõlar väljas</string>
+    <string name="speaker_need_headset">Ühendage kõrvaklapid et seda funktsiooni kasutada.</string>
+    <string name="single_track">"Üksik lugu"</string>
+    <string name="input_url">"Sisesta URL"</string>
+    <string name="streaming_settings">"Voogesituse seaded"</string>
+    <string name="next">"Järgmine"</string>
+    <string name="previous">"Eelmine"</string>
+    <string name="buffer_size">Puhvri suurus</string>
+    <string name="apn">Eelistatud APN</string>
+    <string name="rtp_min_port">Min. port</string>
+    <string name="rtp_max_port">Maks. port</string>
+    <string name="set_rtp_min_port">Sea min. port</string>
+    <string name="set_rtp_max_port">Sea maks. port</string>
+    <string name="set_buffer_size">Määra puhvri suurus</string>
+    <string name="set_apn">Vali eelistatud APN</string>
+    <string name="setting">Seaded</string>
+    <string name="server_timeout_title">"Serveri päring hangus"</string>
+    <string name="server_timeout_message">"Taasühenda serveriga video mängimiseks?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Ühendus ebaõnnestus, taasühendan %1$d\u2026"</string>
+    <string name="media_controller_live">Otse</string>
+    <string name="media_controller_playing">Mängin</string>
+    <string name="media_controller_connecting">Ühendun\u2026</string>
+    <string name="bookmark_add">"Lisa järjehoidja"</string>
+    <string name="bookmark_display">"Kuva järjehoidjad"</string>
+    <string name="bookmark_empty">"Järjehoidjad puuduvad"</string>
+    <string name="bookmark_exist">"Järjehoidja juba eksisteerib"</string>
+    <string name="bookmark_add_success">"Järjehoidja lisatud"</string>
+    <string name="bookmark_list">"Järjehoidjad"</string>
+    <string name="bookmark_title">"Pealkiri"</string>
+    <string name="bookmark_location">"Asukoht"</string>
+    <string name="delete_all">"Kustuta kõik"</string>
+    <string name="default_title">"Vaikimisi pealkiri"</string>
+    <string name="more_image">Rohkem pilte</string>
+    <string name="mute_nosupport">Ei saa vaigistada : video pole toetatud</string>
+    <string name="map_activity_not_found_err">Kaardirakendust pole installeeritud asukoha näitamiseks.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videot</item>
+    </plurals>
+    <string name="share_dialogue_title">Jaga läbi</string>
+    <string name="fail_trim">Vabandust, seda videofaili ei saa kärpida</string>
+    <string name="drm_license_info">DRM litsensi info</string>
+    <string name="albums_title">Albumid</string>
+    <string name="videos_title">Videod</string>
+    <string name="action_viewtype_list">Loendivaade</string>
+    <string name="tvEmptyAlbum">Fotod puuduvad</string>
+    <string name="tvEmptyVideos">Videod puuduvad</string>
+</resources>
diff --git a/res/values-eu/cm_strings.xml b/res/values-eu/cm_strings.xml
new file mode 100644
index 0000000..2934286
--- /dev/null
+++ b/res/values-eu/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Grabaketaren ordua</string>
+</resources>
diff --git a/res/values-eu/codeaurora_strings.xml b/res/values-eu/codeaurora_strings.xml
new file mode 100644
index 0000000..5cb65bb
--- /dev/null
+++ b/res/values-eu/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Urratsa</string>
+    <string name="step_option_desc">Pertsonalizatu aurrera/atzerako jauziak</string>
+    <string name="setp_option_three_second">3 segundo</string>
+    <string name="setp_option_six_second">6 segundo</string>
+    <string name="loop">"Bigiztatu"</string>
+    <string name="single">"Bakarra"</string>
+    <string name="stereo">"Estereoa"</string>
+    <string name="speaker_on">Bozgorailua piztuta</string>
+    <string name="speaker_off">Bozgorailua itzalita</string>
+    <string name="speaker_need_headset">Konektatu aurikularrak ezaugarri hau erabiltzeko.</string>
+    <string name="single_track">"Pista bakarra"</string>
+    <string name="input_url">"Sartu URLa"</string>
+    <string name="streaming_settings">"Transmisio jarraituaren ezarpenak"</string>
+    <string name="next">"Hurrengoa"</string>
+    <string name="previous">"Aurrekoa"</string>
+    <string name="buffer_size">Buffer neurria</string>
+    <string name="apn">APN hobetsia</string>
+    <string name="rtp_min_port">Gutxieneko ataka</string>
+    <string name="rtp_max_port">Gehieneko ataka</string>
+    <string name="set_rtp_min_port">Ezarri gutxieneko ataka</string>
+    <string name="set_rtp_max_port">Ezarri gehieneko ataka</string>
+    <string name="set_buffer_size">Ezarri buffer neurria</string>
+    <string name="set_apn">Ezarri APN hobetsia</string>
+    <string name="setting">Ezarpenak</string>
+    <string name="server_timeout_title">"Zerbitzariaren denbora-muga"</string>
+    <string name="server_timeout_message">"Zerbitzarira birkonektatu bideoa erreproduzitzeko?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Konexioak huts egin du, %1$d birkonektatzen\u2026"</string>
+    <string name="media_controller_live">Zuzenean</string>
+    <string name="media_controller_playing">Erreproduzitzen</string>
+    <string name="media_controller_connecting">Konektatzen\u2026</string>
+    <string name="bookmark_add">"Gehitu laster-marka"</string>
+    <string name="bookmark_display">"Erakutsi Laster-markak"</string>
+    <string name="bookmark_empty">"Ez dago laster-markarik"</string>
+    <string name="bookmark_exist">"Laster-marka badago aurretik"</string>
+    <string name="bookmark_add_success">"Laster-marka gehitu da"</string>
+    <string name="bookmark_list">"Laster-markak"</string>
+    <string name="bookmark_title">"Izenburua"</string>
+    <string name="bookmark_location">"Kokalekua"</string>
+    <string name="delete_all">"Ezabatu guztiak"</string>
+    <string name="default_title">"Izenburu lehenetsia"</string>
+    <string name="more_image">Irudi gehiago</string>
+    <string name="mute_nosupport">Ezin da mututu: bideoa ez da onartzen</string>
+    <string name="map_activity_not_found_err">Ez dago kokalekua bistaratu dezakeen mapa aplikaziorik instalatuta.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">bideo %1$d</item>
+        <item quantity="other">%1$d bideo</item>
+    </plurals>
+    <string name="cannot_share_items">Partekatzeko aukeratutako elementu kopuru maximoa 300 da</string>
+    <string name="share_dialogue_title">Partekatu honen bidez</string>
+    <string name="no_faces">Aurpegirik ez</string>
+    <string name="fail_trim">Barkatu, bideo hau ezin da ebaki</string>
+    <string name="can_not_trim">mp4 eta 3gp fitxategiak baino ezin dira ebaki</string>
+    <string name="drm_license_info">DRM lizentziaren informazioa</string>
+    <string name="timeline_title">Denbora-lerroa</string>
+    <string name="albums_title">Albumak</string>
+    <string name="videos_title">Bideoak</string>
+    <string name="action_viewtype_list">Zerrenda ikuspegia</string>
+    <string name="tvEmptyAlbum">Ez da argazkirik aurkitu</string>
+    <string name="tvEmptyVideos">Ez da bideorik aurkitu</string>
+    <string name="text_makeup_whiten">Zuritu</string>
+    <string name="text_makeup_Soften">Xamurtu</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">Arrunta</string>
+    <string name="truescanner_white">Arbela zuria</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Kendu dirdira</string>
+    <string name="hazebuster_acts">Laino kentzailea</string>
+    <string name="seestraight_acts">Ikusi garbi</string>
+    <string name="seestraight_input_image_is_small">Sarrera-irudia txikiegia da prozesatzeko.</string>
+    <string name="seestraight_process_fail">Ezin izan da irudia prozesatu.</string>
+    <string name="trim_video_exit_title">Baztertu aldaketak?</string>
+    <string name="trim_video_exit_msg">Baztertu bideo honi egindako aldaketak?</string>
+    <string name="trim_video_exit_discard">BAZTERTU</string>
+</resources>
diff --git a/res/values-fa/cm_strings.xml b/res/values-fa/cm_strings.xml
new file mode 100644
index 0000000..954d1c5
--- /dev/null
+++ b/res/values-fa/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">زمان ضبط</string>
+</resources>
diff --git a/res/values-fa/codeaurora_strings.xml b/res/values-fa/codeaurora_strings.xml
new file mode 100644
index 0000000..45ab80f
--- /dev/null
+++ b/res/values-fa/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">گام</string>
+    <string name="step_option_desc">سفارشی کردن گام رو به جلو/عقب سریع</string>
+    <string name="setp_option_three_second">۳ ثانیه</string>
+    <string name="setp_option_six_second">۶ ثانیه</string>
+    <string name="loop">"تکرار"</string>
+    <string name="single">"تکی"</string>
+    <string name="stereo">"استریو"</string>
+    <string name="speaker_on">بلندگو روشن</string>
+    <string name="speaker_off">بلندگو خاموش</string>
+    <string name="speaker_need_headset">برای استفاده از این قابلیت هدفون را وصل کنید.</string>
+    <string name="single_track">"تک‌آهنگ"</string>
+    <string name="input_url">"آدرس را وارد کنید"</string>
+    <string name="streaming_settings">"تنظیمات پخش"</string>
+    <string name="next">"بعدی"</string>
+    <string name="previous">"قبلی"</string>
+    <string name="buffer_size">اندازه بافر</string>
+    <string name="apn">APN ترجیحی</string>
+    <string name="rtp_min_port">پورت min</string>
+    <string name="rtp_max_port">پورت max</string>
+    <string name="set_rtp_min_port">تنظیم پورت min</string>
+    <string name="set_rtp_max_port">تنظیم پورت max</string>
+    <string name="set_buffer_size">تنظیم اندازه بافر</string>
+    <string name="set_apn">انتخاب APN ترجیحی</string>
+    <string name="setting">تنظیمات</string>
+    <string name="server_timeout_title">"پایان زمان سرور"</string>
+    <string name="server_timeout_message">"برای پخش مجدد ویدیو دوباره به سرور متصل می‌شوید؟"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"اتصال ناموفق بود، تلاش مجدد برای اتصال به %1$d\u2026"</string>
+    <string name="media_controller_live">زنده</string>
+    <string name="media_controller_playing">در حال پخش</string>
+    <string name="media_controller_connecting">اتصال\u2026</string>
+    <string name="bookmark_add">"افزودن نشانک"</string>
+    <string name="bookmark_display">"نمایش نشانک‌ها"</string>
+    <string name="bookmark_empty">"بدون نشانک"</string>
+    <string name="bookmark_exist">"نشانک از قبل وجود دارد"</string>
+    <string name="bookmark_add_success">"نشانک اضافه شد"</string>
+    <string name="bookmark_list">"نشانک‌ها"</string>
+    <string name="bookmark_title">"عنوان"</string>
+    <string name="bookmark_location">"مکان"</string>
+    <string name="delete_all">"حذف همه"</string>
+    <string name="default_title">"عنوان پیش‌فرض"</string>
+    <string name="more_image">تصاویر بیشتر</string>
+    <string name="mute_nosupport">نمی‌توان قطع کرد: ویدیو پشتیبانی نمی‌شود</string>
+    <string name="map_activity_not_found_err">برنامه‌ی نقشه‌ای برای نمایش مکان نصب نشده است.</string>
+    <string name="fail_trim">متأسفانه این ویدیو بریده نمی‌شود</string>
+    <string name="drm_license_info">اطلاعات مجوز DRM</string>
+</resources>
diff --git a/res/values-fi/cm_strings.xml b/res/values-fi/cm_strings.xml
new file mode 100644
index 0000000..b811799
--- /dev/null
+++ b/res/values-fi/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tallennusaika</string>
+</resources>
diff --git a/res/values-fi/codeaurora_strings.xml b/res/values-fi/codeaurora_strings.xml
new file mode 100644
index 0000000..9de6726
--- /dev/null
+++ b/res/values-fi/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Kelaus</string>
+    <string name="step_option_desc">Mukauta kelauksen nopeutta</string>
+    <string name="setp_option_three_second">3 sekuntia</string>
+    <string name="setp_option_six_second">6 sekuntia</string>
+    <string name="loop">"Jatkuva"</string>
+    <string name="single">"Yksittäinen"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Kaiutin KÄYTÖSSÄ</string>
+    <string name="speaker_off">Kaiutin POIS KÄYTÖSTÄ</string>
+    <string name="speaker_need_headset">Kytke kuulokkeet käyttääksesi tätä toimintoa.</string>
+    <string name="single_track">"Yksi kappale"</string>
+    <string name="input_url">"Syötä linkki"</string>
+    <string name="streaming_settings">"Suoratoistoasetukset"</string>
+    <string name="next">"Seuraava"</string>
+    <string name="previous">"Edellinen"</string>
+    <string name="buffer_size">Puskurin koko</string>
+    <string name="apn">Ensisijainen APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Aseta min port</string>
+    <string name="set_rtp_max_port">Aseta max port</string>
+    <string name="set_buffer_size">Aseta puskurin koko</string>
+    <string name="set_apn">Valitse ensisijainen APN</string>
+    <string name="setting">Asetukset</string>
+    <string name="server_timeout_title">"Palvelimen aikakatkaisu"</string>
+    <string name="server_timeout_message">"Yhdistä uudelleen palvelimeen toistaaksesi videon?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Yhteys epäonnistui, uudelleenyhdistetään %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Toistetaan</string>
+    <string name="media_controller_connecting">Yhdistetään\u2026</string>
+    <string name="bookmark_add">"Lisää kirjanmerkki"</string>
+    <string name="bookmark_display">"Näytä kirjanmerkit"</string>
+    <string name="bookmark_empty">"Ei kirjanmerkkejä"</string>
+    <string name="bookmark_exist">"Kirjanmerkki on jo olemassa"</string>
+    <string name="bookmark_add_success">"Kirjanmerkki lisätty"</string>
+    <string name="bookmark_list">"Kirjanmerkit"</string>
+    <string name="bookmark_title">"Nimi"</string>
+    <string name="bookmark_location">"Sijainti"</string>
+    <string name="delete_all">"Poista kaikki"</string>
+    <string name="default_title">"Oletusnimi"</string>
+    <string name="more_image">Lisää kuvia</string>
+    <string name="mute_nosupport">Ei voi mykistää: video ei tuettu</string>
+    <string name="map_activity_not_found_err">Karttasovellusta ei asennettu näyttämään sijaintia.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videota</item>
+    </plurals>
+    <string name="cannot_share_items">Jaettavien kohteiden enimmäismäärä on 300</string>
+    <string name="share_dialogue_title">Jaa sovelluksessa</string>
+    <string name="no_faces">Ei kasvoja</string>
+    <string name="fail_trim">Videotiedostoa ei voi leikata</string>
+    <string name="can_not_trim">Vain mp4- ja 3gp-tiedostoja voidaan leikata</string>
+    <string name="drm_license_info">DRM-lisenssin tiedot</string>
+    <string name="timeline_title">Aikajana</string>
+    <string name="albums_title">Albumit</string>
+    <string name="videos_title">Videot</string>
+    <string name="action_viewtype_list">Listanäkymä</string>
+    <string name="tvEmptyAlbum">Kuvia ei löytynyt</string>
+    <string name="tvEmptyVideos">Videoita ei löytynyt</string>
+    <string name="text_makeup_whiten">Valkaisu</string>
+    <string name="text_makeup_Soften">Pehmennys</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Isot silmät</string>
+    <string name="truescanner_normal">Normaali</string>
+    <string name="truescanner_white">Valkotaulu</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Poista häikäisy</string>
+    <string name="hazebuster_acts">Sumun poisto</string>
+    <string name="seestraight_acts">Katso suoraan</string>
+    <string name="seestraight_input_image_is_small">Kuva on liian pieni käsiteltäväksi.</string>
+    <string name="seestraight_process_fail">Kuvan ei voitu käsitellä.</string>
+    <string name="trim_video_exit_title">Hylätäänkö muutokset?</string>
+    <string name="trim_video_exit_msg">Hylkää videoon tekemäsi muutokset?</string>
+    <string name="trim_video_exit_discard">HYLKÄÄ</string>
+</resources>
diff --git a/res/values-fr/cm_strings.xml b/res/values-fr/cm_strings.xml
new file mode 100644
index 0000000..33de10d
--- /dev/null
+++ b/res/values-fr/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Date et heure d\'enregistrement</string>
+</resources>
diff --git a/res/values-fr/codeaurora_strings.xml b/res/values-fr/codeaurora_strings.xml
new file mode 100644
index 0000000..c8b17ea
--- /dev/null
+++ b/res/values-fr/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Étape</string>
+    <string name="step_option_desc">Personnaliser le saut de l\'avance/retour rapide</string>
+    <string name="setp_option_three_second">3 secondes</string>
+    <string name="setp_option_six_second">6 secondes</string>
+    <string name="loop">"Boucle"</string>
+    <string name="single">"Simple"</string>
+    <string name="stereo">"Stéréo"</string>
+    <string name="speaker_on">Haut-parleur activé</string>
+    <string name="speaker_off">Haut-parleur désactivé</string>
+    <string name="speaker_need_headset">Brancher un casque pour utiliser cette fonctionnalité.</string>
+    <string name="single_track">"Piste simple"</string>
+    <string name="input_url">"Entrer l'URL"</string>
+    <string name="streaming_settings">"Paramètres de transmission"</string>
+    <string name="next">"Suivant"</string>
+    <string name="previous">"Précédent"</string>
+    <string name="buffer_size">Taille du tampon</string>
+    <string name="apn">APN préféré</string>
+    <string name="rtp_min_port">Port minimum</string>
+    <string name="rtp_max_port">Port maximum</string>
+    <string name="set_rtp_min_port">Configurer le port minimal</string>
+    <string name="set_rtp_max_port">Configurer le port maximal</string>
+    <string name="set_buffer_size">Paramétrer la taille du tampon</string>
+    <string name="set_apn">Sélectionner l\'APN préféré</string>
+    <string name="setting">Paramètres</string>
+    <string name="server_timeout_title">"Délai de réponse du serveur dépassé"</string>
+    <string name="server_timeout_message">"Se reconnecter au serveur pour lire la vidéo ?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"La connexion a échoué, tentative de reconnexion à %1$d\u2026"</string>
+    <string name="media_controller_live">En direct</string>
+    <string name="media_controller_playing">Lecture</string>
+    <string name="media_controller_connecting">Connexion\u2026</string>
+    <string name="bookmark_add">"Ajouter un favori"</string>
+    <string name="bookmark_display">"Afficher les favoris"</string>
+    <string name="bookmark_empty">"Aucun favori"</string>
+    <string name="bookmark_exist">"Le favori existe déjà"</string>
+    <string name="bookmark_add_success">"Favori ajouté"</string>
+    <string name="bookmark_list">"Favoris"</string>
+    <string name="bookmark_title">"Titre"</string>
+    <string name="bookmark_location">"Position"</string>
+    <string name="delete_all">"Tout supprimer"</string>
+    <string name="default_title">"Titre par défaut"</string>
+    <string name="more_image">Plus d\'images</string>
+    <string name="mute_nosupport">Coupure du son impossible : vidéo non prise en charge</string>
+    <string name="map_activity_not_found_err">Il n\'y a aucune application de cartographie installée pour afficher la position.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vidéo</item>
+        <item quantity="other">%1$d vidéos</item>
+    </plurals>
+    <string name="cannot_share_items">Le nombre maximum d\'éléments sélectionnés pour le partage est de 300</string>
+    <string name="share_dialogue_title">Partager via</string>
+    <string name="no_faces">Pas de visages</string>
+    <string name="fail_trim">Désolé, cette vidéo ne peut pas être coupée</string>
+    <string name="can_not_trim">Seuls les fichiers mp4 et 3gp peuvent être tronqués</string>
+    <string name="drm_license_info">Infos sur la licence DRM</string>
+    <string name="timeline_title">Chronologie</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Vidéos</string>
+    <string name="action_viewtype_list">Affichage liste</string>
+    <string name="tvEmptyAlbum">Aucune photo trouvée</string>
+    <string name="tvEmptyVideos">Aucune vidéo trouvée</string>
+    <string name="text_makeup_whiten">Blanchir</string>
+    <string name="text_makeup_Soften">Adoucir</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Filtre grand yeux</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Tableau blanc</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Supprimer les reflets</string>
+    <string name="hazebuster_acts">Filtre anti-brume</string>
+    <string name="seestraight_acts">Voir directement</string>
+    <string name="seestraight_input_image_is_small">L\'image d\'origine est trop petite pour être traitée.</string>
+    <string name="seestraight_process_fail">Impossible de traiter l\'image.</string>
+    <string name="trim_video_exit_title">Ignorer les modifications ?</string>
+    <string name="trim_video_exit_msg">Ignorer les modifications apportées à cette vidéo ?</string>
+    <string name="trim_video_exit_discard">ANNULER</string>
+</resources>
diff --git a/res/values-fy-rNL/cm_strings.xml b/res/values-fy-rNL/cm_strings.xml
new file mode 100644
index 0000000..c3607ff
--- /dev/null
+++ b/res/values-fy-rNL/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tiid fan opname</string>
+</resources>
diff --git a/res/values-fy-rNL/codeaurora_strings.xml b/res/values-fy-rNL/codeaurora_strings.xml
new file mode 100644
index 0000000..4922de0
--- /dev/null
+++ b/res/values-fy-rNL/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Stap</string>
+    <string name="step_option_desc">Stapgrutte foarút-/tebekspiele oanpasse</string>
+    <string name="setp_option_three_second">3 sekonden</string>
+    <string name="setp_option_six_second">6 sekonden</string>
+    <string name="loop">"Werhelje"</string>
+    <string name="single">"Inkeld"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Lûdsprekker OAN</string>
+    <string name="speaker_off">Lûdsprekker ÚT</string>
+    <string name="speaker_need_headset">Slút in koptelefoan oan om dizze funksje te brûken.</string>
+    <string name="single_track">"Ien nûmer"</string>
+    <string name="input_url">"URL ynfiere"</string>
+    <string name="streaming_settings">"Ynstellingen foar streaming"</string>
+    <string name="next">"Folgjende"</string>
+    <string name="previous">"Foarige"</string>
+    <string name="buffer_size">Buffergrutte</string>
+    <string name="apn">Foarkars-APN</string>
+    <string name="rtp_min_port">Min. poarte</string>
+    <string name="rtp_max_port">Maks. poarte</string>
+    <string name="set_rtp_min_port">Minimale poarte ynstelle</string>
+    <string name="set_rtp_max_port">Maksimale poarte ynstelle</string>
+    <string name="set_buffer_size">Buffergrutte ynstelle</string>
+    <string name="set_apn">Foarkars-APN selektearje</string>
+    <string name="setting">Ynstellingen</string>
+    <string name="server_timeout_title">"Time-out fan de server"</string>
+    <string name="server_timeout_message">"Opnij ferbining meitsje mei de server om de fideo ôf te spyljen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Ferbining mislearre, probearret opnij ferbining te meitsjen mei %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Spilet</string>
+    <string name="media_controller_connecting">Ferbining meitsje\u2026</string>
+    <string name="bookmark_add">"Blêdwizer tafoegje"</string>
+    <string name="bookmark_display">"Blêdwizers toane"</string>
+    <string name="bookmark_empty">"Gjin blêdwizers"</string>
+    <string name="bookmark_exist">"Blêdwizer bestiet al"</string>
+    <string name="bookmark_add_success">"Blêdwizer tafoege"</string>
+    <string name="bookmark_list">"Blêdwizers"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Lokaasje"</string>
+    <string name="delete_all">"Alles fuortsmite"</string>
+    <string name="default_title">"Standerttitel"</string>
+    <string name="more_image">Mear ôfbyldingen</string>
+    <string name="mute_nosupport">Kin lûd net dôvje: fideo net stipe</string>
+    <string name="map_activity_not_found_err">Der is gjin kaarten-app ynstallearre om de lokaasje te toanen.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d fideo</item>
+        <item quantity="other">%1$d fideo\'s</item>
+    </plurals>
+    <string name="cannot_share_items">Maksimaal oantal items dat dield wurde kin is 300</string>
+    <string name="share_dialogue_title">Diele fia</string>
+    <string name="no_faces">Gjin gedichten</string>
+    <string name="fail_trim">Kin dizze fideo net bysnije</string>
+    <string name="can_not_trim">Allinnich mp4- en 3gp-bestannen kinne bysnijen wurde</string>
+    <string name="drm_license_info">DRM-lisinsjeynformaasje</string>
+    <string name="timeline_title">Tiidline</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Fideo\'s</string>
+    <string name="action_viewtype_list">Listwerjefte</string>
+    <string name="tvEmptyAlbum">Gjin foto\'s fûn</string>
+    <string name="tvEmptyVideos">Gjin fideo\'s fûn</string>
+    <string name="text_makeup_whiten">Witer</string>
+    <string name="text_makeup_Soften">Sêfter</string>
+    <string name="text_makeup_trimface">Gesicht bywurkje</string>
+    <string name="text_makeup_bigeye">Grutte eagen</string>
+    <string name="truescanner_normal">Normaal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Refleksjes fuortsmite</string>
+    <string name="hazebuster_acts">Waas fuortsmite</string>
+    <string name="seestraight_acts">Rjochtút sjen</string>
+    <string name="seestraight_input_image_is_small">Ofbylding is te lyts om te ferwurkjen.</string>
+    <string name="seestraight_process_fail">Kin ôfbylding net ferwurkje.</string>
+    <string name="trim_video_exit_title">Wizigingen ferwerpe?</string>
+    <string name="trim_video_exit_msg">Wizigingen oan dizze fideo ferwerpe?</string>
+    <string name="trim_video_exit_discard">FERWERPE</string>
+</resources>
diff --git a/res/values-gd/cm_strings.xml b/res/values-gd/cm_strings.xml
new file mode 100644
index 0000000..c4cba71
--- /dev/null
+++ b/res/values-gd/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Clàraich an t-àm</string>
+</resources>
diff --git a/res/values-gd/codeaurora_strings.xml b/res/values-gd/codeaurora_strings.xml
new file mode 100644
index 0000000..7814de4
--- /dev/null
+++ b/res/values-gd/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Ceum</string>
+    <string name="step_option_desc">Gnàthaich ceumannan an toinneimh air adhart/air ais</string>
+    <string name="setp_option_three_second">3 diogan</string>
+    <string name="setp_option_six_second">6 diogan</string>
+    <string name="loop">"Lùb"</string>
+    <string name="single">"Singilte"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Glaodhaire AIR</string>
+    <string name="speaker_off">Glaodhaire DHETH</string>
+    <string name="speaker_need_headset">Cuir a-steach cluais-fhònaichean airson an gleus seo a chleachdadh.</string>
+    <string name="single_track">"Traca singilte"</string>
+    <string name="input_url">"Cuir a-steach URL"</string>
+    <string name="streaming_settings">"Roghainnean an t-sruthaidh"</string>
+    <string name="next">"Air adhart"</string>
+    <string name="previous">"Air ais"</string>
+    <string name="buffer_size">Meud a’ bhufair</string>
+    <string name="apn">APN as fheàrr leat</string>
+    <string name="rtp_min_port">Port as lugha</string>
+    <string name="rtp_max_port">Port as motha</string>
+    <string name="set_rtp_min_port">Suidhich am port as lugha</string>
+    <string name="set_rtp_max_port">Suidhich am port as motha</string>
+    <string name="set_buffer_size">Suidhich meud a’ bhufair</string>
+    <string name="set_apn">Suidhich an APN as fheàrr leat</string>
+    <string name="setting">Roghainnean</string>
+    <string name="server_timeout_title">"Crìoch-ùine an fhrithealaiche"</string>
+    <string name="server_timeout_message">"A bheil thu airson ceangal ris an fhrithealaiche a-rithist gus a’ video a chluich?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Dh’fhàillig an ceangal, a’ feuchainn ris an ceangal ri %1$d a dhèanamh às ùr\u2026"</string>
+    <string name="media_controller_live">Beò</string>
+    <string name="media_controller_playing">’Ga chluich</string>
+    <string name="media_controller_connecting">’Ga cheangal\u2026</string>
+    <string name="bookmark_add">"Cuir comharra-lìn ris"</string>
+    <string name="bookmark_display">"Seall na comharran-lìn"</string>
+    <string name="bookmark_empty">"Gun chomharran-lìn"</string>
+    <string name="bookmark_exist">"Tha an comharra-lìn seo ann mu thràth"</string>
+    <string name="bookmark_add_success">"Chaidh an comharra-lìn a chur ris"</string>
+    <string name="bookmark_list">"Comharran-lìn"</string>
+    <string name="bookmark_title">"Tiotal"</string>
+    <string name="bookmark_location">"Ionad"</string>
+    <string name="delete_all">"Sguab às na h-uile"</string>
+    <string name="default_title">"An tiotal bunaiteach"</string>
+    <string name="more_image">Barrachd dhealbhan</string>
+    <string name="mute_nosupport">Cha ghabh a mhùchadh : chan eil taic ri video</string>
+    <string name="map_activity_not_found_err">Cha deach aplacaid mhapaichean a stàladh a shealladh an t-ionad.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="two">%1$d video</item>
+        <item quantity="few">%1$d videothan</item>
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Gabhaidh 300 nì taghta a cho-roinneadh air a char as motha</string>
+    <string name="share_dialogue_title">Co-roinn slighe</string>
+    <string name="no_faces">Gun aodann ann</string>
+    <string name="fail_trim">Tha sinn duilich ach cha ghabh am faidhle video seo a bhearradh</string>
+    <string name="can_not_trim">Cha ghabh ach faidhlichean mp4 ’s 3gp a bhearradh</string>
+    <string name="drm_license_info">Fiosrachadh mun cheadachas DRM</string>
+    <string name="timeline_title">Loidhne-ama</string>
+    <string name="albums_title">Albaman</string>
+    <string name="videos_title">Videothan</string>
+    <string name="action_viewtype_list">Sealladh liosta</string>
+    <string name="tvEmptyAlbum">Cha deach dealbh a lorg</string>
+    <string name="tvEmptyVideos">Cha deach video a lorg</string>
+    <string name="text_makeup_whiten">Dèan nas gile</string>
+    <string name="text_makeup_Soften">Bogaich</string>
+    <string name="text_makeup_trimface">Beàrr an t-aodann</string>
+    <string name="text_makeup_bigeye">Sùil mhòr</string>
+    <string name="truescanner_normal">Àbhaisteach</string>
+    <string name="truescanner_white">Clàr-geal</string>
+    <string name="truescanner">Fìor-sganair</string>
+    <string name="truescanner_remove_glare">Thoir deàrrsadh air falbh</string>
+    <string name="hazebuster_acts">Casg air sgeò</string>
+    <string name="seestraight_acts">Coimhead gu dìreach</string>
+    <string name="seestraight_input_image_is_small">Tha an dealbh ro bheag gus a phròiseasadh.</string>
+    <string name="seestraight_process_fail">Cha b’ urrainn dhuinn an dealbh a phròiseasadh.</string>
+    <string name="trim_video_exit_title">A bheil thu airson na h-atharraichean a thilgeil air falbh?</string>
+    <string name="trim_video_exit_msg">A bheil thu airson na h-atharraichean air a’ video seo a thilgeil air falbh?</string>
+    <string name="trim_video_exit_discard">TILG AIR FALBH</string>
+</resources>
diff --git a/res/values-gd/filtershow_strings.xml b/res/values-gd/filtershow_strings.xml
new file mode 100644
index 0000000..1d6b4a2
--- /dev/null
+++ b/res/values-gd/filtershow_strings.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">Deasaiche dhealbhan</string>
+    <string name="cannot_load_image">Chan urrainn dhuinn an dealbh a luchdadh!</string>
+    <string name="cannot_edit_original">Cha ghabh an dealbh tùsail a dheasachadh</string>
+    <string name="original_picture_text">@string/original</string>
+    <string name="setting_wallpaper">A’ suidheachadh a’ phàipeir-bhalla</string>
+    <string name="download_failure">Cha b’ urrainn dhuinn an dealbh a luchdadh a-nuas. Chan eil lìonra ri làimh.</string>
+    <string name="original">Tùsail</string>
+    <string name="borders" msgid="4461692156695893616">Iomallan</string>
+    <string name="custom_border">Gnàthaichte</string>
+    <string name="filtershow_undo">Neo-dhèan</string>
+    <string name="filtershow_redo">Ath-dhèan</string>
+    <string name="show_imagestate_panel">Seall na h-èifeachdan air an cur an sàs</string>
+    <string name="hide_imagestate_panel">Falaich na h-èifeachdan air an cur an sàs</string>
+    <string name="export_image">Às-phortaich</string>
+    <string name="print_image">Clò-bhuail</string>
+    <string name="export_flattened">Às-phortaich dealbh leathnaichte</string>
+    <string name="select_output_settings">Bidh an dealbh air às-phortadh ’na lethbhreac gun eachdraidh.</string>
+    <string name="quality">Càileachd</string>
+    <string name="size">Meud</string>
+    <string name="x">T</string>
+    <string name="menu_settings">Roghainnean</string>
+    <string name="unsaved">Tha atharraichean gun sàbhaladh san dealbh seo.</string>
+    <string name="save_before_exit">A bheil thu airson an sàbhaladh mus fhàg thu an-seo?</string>
+    <string name="save_and_exit">Sàbhail is fàg</string>
+    <string name="save_and_processing">A’ pròiseasadh dealbh air an dùmhlachd-bhreacaidh shlàn…</string>
+    <string name="exit">Fàg</string>
+    <string name="history">Eachdraidh</string>
+    <string name="reset">Ath-shuidhich</string>
+    <string name="history_original">@string/original</string>
+    <string name="imageState">Na h-èifeachdan air an cur an sàs</string>
+    <string name="compare_original">Dèan coimeas</string>
+    <string name="apply_effect">Cuir an sàs</string>
+    <string name="reset_effect">Ath-shuidhich</string>
+    <string name="aspect">Co-mheas deilbh</string>
+    <string name="aspect1to1_effect">1:1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">Chan eil gin</string>
+    <string name="aspectOriginal_effect">@string/original</string>
+    <string name="Fixed">Socraichte</string>
+    <string name="tinyplanet">Planaid bhìodach</string>
+    <string name="exposure" msgid="1229093066434614811">Deisearas</string>
+    <string name="sharpness">Gèiread</string>
+    <string name="contrast">Iomsgaradh</string>
+    <string name="vibrance">Beòthail</string>
+    <string name="saturation">Sàthachd</string>
+    <string name="bwfilter">Criathrag dubh/gheal</string>
+    <string name="wbalance">Dathan fèin-obrachail</string>
+    <string name="hue">Tuar</string>
+    <string name="shadow_recovery">Sgàilean</string>
+    <string name="highlight_recovery">Soillseachadh</string>
+    <string name="curvesRGB">Lùban</string>
+    <string name="vignette">Vignette</string>
+    <string name="vignette_main">Vignette</string>
+    <string name="vignette_exposure">Deisearas</string>
+    <string name="vignette_saturation">Sàthachd</string>
+    <string name="vignette_contrast">Iomsgaradh</string>
+    <string name="vignette_falloff">Crìonadh solais</string>
+    <string name="redeye">Sùil dhearg</string>
+    <string name="imageDraw">Tarraing</string>
+    <string name="straighten" msgid="5217801513491493491">Dèan dìreach</string>
+    <string name="crop" msgid="5584000454518174632">Beàrr</string>
+    <string name="rotate" msgid="460017689320955494">Cuairtich</string>
+    <string name="mirror">Sgàthanaich</string>
+    <string name="negative">Ais-thionndaidh</string>
+    <string name="none" msgid="3601545724573307541">Chan eil gin</string>
+    <string name="edge">Oirean</string>
+    <string name="kmeans">Postairich</string>
+    <string name="downsample">Samplaich sìos</string>
+    <string name="grad">Ceumnaichte</string>
+    <string name="editor_grad_brightness">Soilleireachd</string>
+    <string name="editor_grad_contrast">Iomsgaradh</string>
+    <string name="editor_grad_saturation">Sàthachd</string>
+    <string name="editor_chan_sat_main">Prìomh-shàthachd</string>
+    <string name="editor_chan_sat_red">Dearg</string>
+    <string name="editor_chan_sat_yellow">Buidhe</string>
+    <string name="editor_chan_sat_green">Uaine</string>
+    <string name="editor_chan_sat_cyan">Saidhean</string>
+    <string name="editor_chan_sat_blue">Gorm</string>
+    <string name="editor_chan_sat_magenta">Magenta</string>
+    <string name="editor_grad_style">Stoidhle</string>
+    <string name="editor_grad_new">ùr</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">Dearg</string>
+    <string name="curves_channel_green">Uaine</string>
+    <string name="curves_channel_blue">Gorm</string>
+    <string name="draw_style">Stoidhle</string>
+    <string name="draw_size">Meud</string>
+    <string name="draw_hue">Tuar</string>
+    <string name="draw_saturation">Sàthachd</string>
+    <string name="draw_value">Soilleireachd</string>
+    <string name="draw_color">Dath</string>
+    <string name="draw_style_line">Loidhnichean</string>
+    <string name="draw_style_brush_spatter">Comharraiche</string>
+    <string name="draw_style_brush_marker">Gànraich</string>
+    <string name="draw_clear">Falamhaich</string>
+    <string name="color_border_size">Tiughad</string>
+    <string name="color_border_corner_size">Meud nan oisean</string>
+    <string name="color_border_color">Dath</string>
+    <string name="color_border_clear">Falamhaich</string>
+    <string name="color_pick_select">Tagh dath gnàthaichte</string>
+    <string name="color_pick_title">Tagh dath</string>
+    <string name="draw_size_title">Tagh meud</string>
+    <string name="draw_size_accept">Ceart ma-thà</string>
+    <string name="state_panel_original">Tùsail</string>
+    <string name="state_panel_result">Toradh</string>
+    <string name="filtershow_notification_label">A’ sàbhaladh an deilbh</string>
+    <string name="filtershow_notification_message">’Ga phròiseasadh…</string>
+    <string name="filtershow_save_preset">Sàbhail an ro-sheata làithreach</string>
+    <string name="filtershow_manage_preset">Stiùir ro-sheataichean a’ chleachdaiche</string>
+    <string name="filtershow_new_preset">Ro-sheata ùr</string>
+    <string name="filtershow_preset_name">Ainm an ro-sheata</string>
+    <string name="filtershow_show_info_panel">Fiosrachadh</string>
+    <string name="filtershow_show_info_panel_name">Ainm an deilbh</string>
+    <string name="filtershow_show_info_panel_size">Meud an deilbh</string>
+    <string name="filtershow_show_info_panel_histogram">Hiostogram</string>
+    <string name="filtershow_show_info_panel_exif">Dàta EXIF</string>
+    <string name="filtershow_add_button_looks">Ro-sheata</string>
+    <string name="filtershow_add_button_versions">Tionndadh</string>
+    <string name="filtershow_version_original">Tùsail</string>
+    <string name="filtershow_version_current">Làithreach</string>
+    <string name="filtershow_exif_model">Modail</string>
+    <string name="filtershow_exif_aperture">Fosgladh</string>
+    <string name="filtershow_exif_focal_length">Faid an fhòcais</string>
+    <string name="filtershow_exif_iso">ISO</string>
+    <string name="filtershow_exif_subject_distance">Astar a’ chuspair</string>
+    <string name="filtershow_exif_date">Air a thogail</string>
+    <string name="filtershow_exif_f_stop">Stad F</string>
+    <string name="filtershow_exif_exposure_time">Faid an deisearais</string>
+    <string name="filtershow_exif_copyright">Còir-lethbhreac</string>
+</resources>
diff --git a/res/values-gd/strings.xml b/res/values-gd/strings.xml
new file mode 100644
index 0000000..ce08d23
--- /dev/null
+++ b/res/values-gd/strings.xml
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Gailearaidh</string>
+    <string name="gadget_title">Frèam deilbh</string>
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="movie_view_label">Cluicheadair video</string>
+    <string name="loading_video">A’ luchdadh a’ video\u2026</string>
+    <string name="loading_image">A’ luchdadh an deilbh\u2026</string>
+    <string name="loading_account">A’ luchdadh a’ chunntais\u2026</string>
+    <string name="resume_playing_title">Lean air a’ video</string>
+    <string name="resume_playing_message">An lean thu air a’ chluich o %s ?</string>
+    <string name="resume_playing_resume">Lean air a chluich</string>
+    <string name="loading">’Ga luchdadh\u2026</string>
+    <string name="fail_to_load">Cha b’ urrainn dhuinn a luchdadh</string>
+    <string name="fail_to_load_image">Cha b’ urrainn dhuinn an dealbh a luchdadh</string>
+    <string name="no_thumbnail">Gun dealbhag</string>
+    <string name="resume_playing_restart">Tòisich às ùr</string>
+    <string name="crop_save_text">Ceart ma-thà</string>
+    <string name="ok">Ceart ma-thà</string>
+    <string name="multiface_crop_help">Suath ri aodann airson tòiseachadh.</string>
+    <string name="saving_image">A’ sàbhaladh an deilbh\u2026</string>
+    <string name="filtershow_saving_image">A’ sàbhaladh an deilbh gu <xliff:g id="album_name">%1$s</xliff:g> \u2026</string>
+    <string name="save_error">Cha b’ urrainn dhuinn an dealbh beàrrte a shàbhaladh.</string>
+    <string name="crop_label">Beàrr an dealbh</string>
+    <string name="trim_label">Beàrr a’ video</string>
+    <string name="select_image">Tagh dealbh</string>
+    <string name="select_video">Tagh video</string>
+    <string name="select_item">Tagh nì</string>
+    <string name="select_album">Tagh albam</string>
+    <string name="select_group">Tagh buidheann</string>
+    <string name="set_image">Suidhich an dealbh mar</string>
+    <string name="set_wallpaper">Suidhich pàipear-balla</string>
+    <string name="wallpaper">A’ suidheachadh a’ phàipeir-bhalla\u2026</string>
+    <string name="camera_setas_wallpaper">Pàipear-balla</string>
+    <string name="delete">Sguab às</string>
+    <plurals name="delete_selection">
+        <item quantity="one">A bheil thu airson an nì a thagh thu a sguabadh às?</item>
+        <item quantity="two">A bheil thu airson na nithean a thagh thu a sguabadh às?</item>
+        <item quantity="few">A bheil thu airson na nithean a thagh thu a sguabadh às?</item>
+        <item quantity="other">A bheil thu airson na nithean a thagh thu a sguabadh às?</item>
+    </plurals>
+    <string name="confirm">Dearbh</string>
+    <string name="cancel">Sguir dheth</string>
+    <string name="share">Co-roinn</string>
+    <string name="share_panorama">Co-roinn an cuairt-shealladh</string>
+    <string name="share_as_photo">Co-roinn ’na dhealbh</string>
+    <string name="deleted">Chaidh a sguabadh às</string>
+    <string name="undo">NEO-DHÈAN</string>
+    <string name="select_all">Tagh na h-uile</string>
+    <string name="deselect_all">Dì-thagh na h-uile</string>
+    <string name="slideshow">Taisbeanadh-shleamhnagan</string>
+    <string name="details">Mion-fhiosrachadh</string>
+    <string name="details_title">%1$d à %2$d nì:</string>
+    <string name="close">Dùin</string>
+    <string name="switch_to_camera">Atharraich gun mhodh chamara</string>
+    <plurals name="number_of_items_selected">
+        <item quantity="one">Chaidh %1$d a thaghadh</item>
+        <item quantity="two">Chaidh %1$d a thaghadh</item>
+        <item quantity="few">Chaidh %1$d a thaghadh</item>
+        <item quantity="other">Chaidh %1$d a thaghadh</item>
+    </plurals>
+    <plurals name="number_of_albums_selected">
+        <item quantity="one">Chaidh %1$d a thaghadh</item>
+        <item quantity="two">Chaidh %1$d a thaghadh</item>
+        <item quantity="few">Chaidh %1$d a thaghadh</item>
+        <item quantity="other">Chaidh %1$d a thaghadh</item>
+    </plurals>
+    <plurals name="number_of_groups_selected">
+        <item quantity="one">Chaidh %1$d a thaghadh</item>
+        <item quantity="two">Chaidh %1$d a thaghadh</item>
+        <item quantity="few">Chaidh %1$d a thaghadh</item>
+        <item quantity="other">Chaidh %1$d a thaghadh</item>
+    </plurals>
+    <string name="show_on_map">Seall air mapa</string>
+    <string name="rotate_left">Cuairtich gu tuathail</string>
+    <string name="rotate_right">Cuairtich gu deiseil</string>
+    <string name="no_such_item">Cha b’ urrainn dhuinn an nì a lorg.</string>
+    <string name="edit">Deasaich</string>
+    <string name="simple_edit">Deasachadh sìmplidh</string>
+    <string name="process_caching_requests">A’ pròiseasadh iarrtasan an tasgadain</string>
+    <string name="caching_label">’Ga chur dhan tasgadan\u2026</string>
+    <string name="crop_action">Beàrr</string>
+    <string name="trim_action">Beàrr</string>
+    <string name="mute_action">Mùch</string>
+    <string name="set_as">Suidhich mar</string>
+    <string name="video_mute_err">Cha ghabh a’ video a mhùchadh.</string>
+    <string name="video_err">Cha ghabh a’ video a chluich.</string>
+    <string name="group_by_location">A-rèir ionaid</string>
+    <string name="group_by_time">A-rèir ama</string>
+    <string name="group_by_tags">A-rèir thagaichean</string>
+    <string name="group_by_faces">A-rèir dhaoine</string>
+    <string name="group_by_album">A-rèir albaim</string>
+    <string name="group_by_size">A-rèir meud</string>
+    <string name="untagged">Gun taga</string>
+    <string name="no_location">Gun ionad</string>
+    <string name="no_connectivity">Cha do dh’aithnich sinn gach ionad ri linn duilgheadasan leis an lìonra.</string>
+    <string name="sync_album_error">Cha b’ urrainn dhuinn na dealbhan san albam seo a luchdadh a-nuas. Feuch ris a-rithist uaireigin eile.</string>
+    <string name="show_images_only">Dealbhan a-mhàin</string>
+    <string name="show_videos_only">Videothan a-mhàin</string>
+    <string name="show_all">Dealbhan ⁊ videothan</string>
+    <string name="appwidget_title">Gailearaidh dhealbhan</string>
+    <string name="appwidget_empty_text">Chan eil dealbh ann.</string>
+    <string name="crop_saved">        Chaidh an dealbh beàrrte a shàbhaladh gu <xliff:g id="folder_name">%s</xliff:g>.</string>
+    <string name="no_albums_alert">Chan eil albam ann.</string>
+    <string name="empty_album">Chan eil dealbh no video ann.</string>
+    <string name="picasa_posts">Postaichean</string>
+    <string name="make_available_offline">Cuir ri làimh far loidhne</string>
+    <string name="sync_picasa_albums">Ath-nuadhaich</string>
+    <string name="done">Deiseil</string>
+    <string name="sequence_in_set">%1$d à %2$d nì:</string>
+    <string name="title">Tiotal</string>
+    <string name="description">Tuairisgeul</string>
+    <string name="time">Àm</string>
+    <string name="location">Ionad</string>
+    <string name="path">Slighe</string>
+    <string name="width">Leud</string>
+    <string name="height">Àirde</string>
+    <string name="orientation">Comhair</string>
+    <string name="duration">Faid</string>
+    <string name="mimetype">Seòrsa MIME</string>
+    <string name="file_size">Meud an fhaidhle</string>
+    <string name="maker">Ùghdar</string>
+    <string name="model">Modail</string>
+    <string name="flash">Solas-boillsgidh</string>
+    <string name="aperture">Fosgladh</string>
+    <string name="focal_length">Faid an fhòcais</string>
+    <string name="white_balance">Am balans geal</string>
+    <string name="exposure_time">Faid an deisearais</string>
+    <string name="iso">ISO</string>
+    <string name="unit_mm">mm</string>
+    <string name="manual">A làimh</string>
+    <string name="auto">Fèin-obrachail</string>
+    <string name="flash_on">Solas-boillsgidh air</string>
+    <string name="flash_off">Gun solas-boillsgidh</string>
+    <string name="unknown">Chan eil fhios</string>
+    <string name="ffx_original">Tùsail</string>
+    <string name="ffx_vintage">Vintage</string>
+    <string name="ffx_instant">Grad-chamara</string>
+    <string name="ffx_bleach">Gealaich</string>
+    <string name="ffx_blue_crush">Gorm</string>
+    <string name="ffx_bw_contrast">Dubh/Geal</string>
+    <string name="ffx_punch">Fiamh buidhe</string>
+    <string name="ffx_x_process">Tar-phròiseasaich</string>
+    <string name="ffx_washout">Dath cofaidh</string>
+    <string name="ffx_washout_color">Litho</string>
+    <plurals name="make_albums_available_offline">
+        <item quantity="one">A’ cur an albaim ri làimh dhut far loidhne.</item>
+        <item quantity="two">A’ cur nan albaman ri làimh dhut far loidhne.</item>
+        <item quantity="few">A’ cur nan albaman ri làimh dhut far loidhne.</item>
+        <item quantity="other">A’ cur nan albaman ri làimh dhut far loidhne.</item>
+    </plurals>
+    <string name="try_to_set_local_album_available_offline">        Tha an nì seo ’ga stòradh gu h-ionadail ’s ri fhaighinn far loidhne.</string>
+    <string name="set_label_all_albums">Na h-albaman uile</string>
+    <string name="set_label_local_albums">Albaman ionadail</string>
+    <string name="set_label_mtp_devices">Uidheaman MTP</string>
+    <string name="set_label_picasa_albums">Albaman Picasa</string>
+    <string name="free_space_format"><xliff:g id="bytes">%s</xliff:g> saor</string>
+    <string name="size_below"><xliff:g id="size">%1$s</xliff:g> no nas lugha</string>
+    <string name="size_above"><xliff:g id="size">%1$s</xliff:g> no nas motha</string>
+    <string name="size_between"><xliff:g id="min_size">%1$s</xliff:g> gu <xliff:g id="max_size">%2$s</xliff:g></string>
+    <string name="Import">Ion-phortaich</string>
+    <string name="import_complete">Chaidh ion-phortadh</string>
+    <string name="import_fail">Cha deach leis an ion-phortadh</string>
+    <string name="camera_connected">Chaidh camara a cheangal ris.</string>
+    <string name="camera_disconnected">Chaidh camara a thoirt air falbh.</string>
+    <string name="click_import">Suath an-seo airson ion-phortadh</string>
+    <string name="widget_type_album">Tagh albam</string>
+    <string name="widget_type_shuffle">Cuir a h-uile dealbh air thuaiream</string>
+    <string name="widget_type_photo">Tagh dealbh</string>
+    <string name="widget_type">Tagh dealbhan</string>
+    <string name="slideshow_dream_name">Taisbeanadh-shleamhnagan</string>
+    <string name="albums">Albaman</string>
+    <string name="times">Amannan</string>
+    <string name="locations">Ionadan</string>
+    <string name="people">Daoine</string>
+    <string name="tags">Tagaichean</string>
+    <string name="group_by">Buidhnich a-rèir</string>
+    <string name="settings">Roghainnean</string>
+    <string name="add_account">Cuir cunntas ris</string>
+    <string name="folder_camera">Camara</string>
+    <string name="folder_download">Luchdaich a-nuas</string>
+    <string name="folder_edited_online_photos">Dealbhan air loidhne a chaidh a dheasachadh</string>
+    <string name="folder_imported">Air ion-phortadh</string>
+    <string name="folder_screenshot">Glacadh-sgrìn</string>
+    <string name="help">Cobhair</string>
+    <string name="no_external_storage_title">Chan eil stòras ann</string>
+    <string name="no_external_storage">Chan eil stòras air an taobh a-muigh</string>
+    <string name="switch_photo_filmstrip">Sealladh stiall film</string>
+    <string name="switch_photo_grid">Sealladh griod</string>
+    <string name="switch_photo_fullscreen">Sealladh làn-sgrìn</string>
+    <string name="trimming">’Ga bhearradh</string>
+    <string name="muting">’Ga mhùchadh</string>
+    <string name="please_wait">Fuirich ort</string>
+    <string name="save_into">A’ sàbhaladh a’ video gu <xliff:g id="album_name">%1$s</xliff:g> \u2026</string>
+    <string name="trim_too_short">Cha ghabh a bhearradh: Tha a’ video-amais ro ghoirid</string>
+    <string name="pano_progress_text">A’ reandaradh a’ chuairt-sheallaidh</string>
+    <string name="save" msgid="8140440041190264400">Sàbhail</string>
+    <string name="ingest_import">@string/Import</string>
+    <string name="ingest_import_complete">@string/import_complete</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">A’ sganadh na susbaint…</string>
+    <plurals name="ingest_number_of_items_scanned">
+        <item quantity="one">Chaidh %1$d nì a sganadh</item>
+        <item quantity="two">Chaidh %1$d nì a sganadh</item>
+        <item quantity="few">Chaidh %1$d nithean a sganadh</item>
+        <item quantity="other">Chaidh %1$d nì a sganadh</item>
+    </plurals>
+    <plurals name="ingest_number_of_items_selected">
+        <item quantity="one">Chaidh %1$d nì a thaghadh</item>
+        <item quantity="two">Chaidh %1$d nì a thaghadh</item>
+        <item quantity="few">Chaidh %1$d nithean a thaghadh</item>
+        <item quantity="other">Chaidh %1$d nì a thaghadh</item>
+    </plurals>
+    <string name="ingest_sorting" msgid="624687230903648118">’Ga sheòrsachadh…</string>
+    <string name="ingest_scanning_done">Tha an sganadh deiseil</string>
+    <string name="ingest_importing">’Ga ion-phortadh…</string>
+    <string name="ingest_empty_device">Chan eil susbaint air an uidheam seo airson ion-phortadh.</string>
+    <string name="ingest_no_device">Cha deach uidheam MTP a cheangal ris</string>
+    <string name="ingest_switch_photo_grid">@string/switch_photo_grid</string>
+    <string name="ingest_switch_photo_fullscreen">@string/switch_photo_fullscreen</string>
+    <string name="camera_error_title">Mearachd a’ chamara</string>
+    <string name="cannot_connect_camera">Cha ghabh ceangal a dhèanamh ris a’ chamara.</string>
+    <string name="camera_disabled">Chaidh an camara a chur à comas ri linn poileasaidhean tèarainteachd.</string>
+    <string name="camera_label">Camara</string>
+    <string name="wait">Fuirich ort\u2026</string>
+    <string name="no_storage" product="nosdcard">Munntaich stòras USB mus cleachd thu an camara.</string>
+    <string name="no_storage" product="default">Cuir a-steach cairt SD mus cleachd thu an camara.</string>
+    <string name="preparing_sd" product="nosdcard">Ag ullachadh an stòrais USB\u2026</string>
+    <string name="preparing_sd" product="default">Ag ullachadh a’ chairt SD…</string>
+    <string name="access_sd_fail" product="nosdcard">Cha b’ urrainn dhuinn an stòras USB inntrigeadh.</string>
+    <string name="access_sd_fail" product="default">Cha b’ urrainn dhuinn a’ chairt SD inntrigeadh.</string>
+    <string name="review_cancel">SGUIR DHETH</string>
+    <string name="review_ok">DEISEIL</string>
+    <string name="time_lapse_title">Clàradh film luathaichte</string>
+    <string name="pref_camera_id_title">Tagh camara</string>
+    <string name="pref_camera_id_entry_back">Cùl</string>
+    <string name="pref_camera_id_entry_front">Beul</string>
+    <string name="pref_camera_recordlocation_title">Ionad an stòraidh</string>
+    <string name="pref_camera_location_label">IONAD</string>
+    <string name="pref_camera_timer_title">Tìmear cunntaidh sìos</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="one">%d diog</item>
+        <item quantity="two">%d dhiog</item>
+        <item quantity="few">%d diogan</item>
+        <item quantity="other">%d diog</item>
+    </plurals>
+    <string name="pref_camera_timer_sound_default">@string/setting_on_value</string>
+    <string name="pref_camera_timer_sound_title">Dèan bìd rè a’ chunntaidh sìos</string>
+    <string name="setting_off">Dheth</string>
+    <string name="setting_on">Air</string>
+    <string name="pref_video_quality_title">Càileachd a’ video</string>
+    <string name="pref_video_quality_entry_high">Àrd</string>
+    <string name="pref_video_quality_entry_low">Ìosal</string>
+    <string name="pref_video_time_lapse_frame_interval_title">Film luathaichte</string>
+    <string name="pref_camera_settings_category">Roghainnean a’ chamara</string>
+    <string name="pref_camcorder_settings_category">Roghainnean a’ chamara video</string>
+    <string name="pref_camera_picturesize_title">Meud an deilbh</string>
+    <string name="pref_camera_picturesize_entry_13mp">13M piogsail</string>
+    <string name="pref_camera_picturesize_entry_8mp">8M piogsail</string>
+    <string name="pref_camera_picturesize_entry_5mp">5M piogsail</string>
+    <string name="pref_camera_picturesize_entry_4mp">4M piogsail</string>
+    <string name="pref_camera_picturesize_entry_3mp">3M piogsail</string>
+    <string name="pref_camera_picturesize_entry_2mp">2M piogsail</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">2M piogsail (16:9)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">1.3M piogsail</string>
+    <string name="pref_camera_picturesize_entry_1mp">1M piogsail</string>
+    <string name="pref_camera_picturesize_entry_vga">VGA</string>
+    <string name="pref_camera_picturesize_entry_qvga">QVGA</string>
+    <string name="pref_camera_focusmode_title">Modh an fhòcais</string>
+    <string name="pref_camera_focusmode_entry_auto">Fèin-obrachail</string>
+    <string name="pref_camera_focusmode_entry_infinity">Neo-chrìochnachd</string>
+    <string name="pref_camera_focusmode_entry_macro">Macro</string>
+    <string name="pref_camera_focusmode_label_auto">FÈIN-OBRACHAIL</string>
+    <string name="pref_camera_focusmode_label_infinity">NEO-CHRÌOCHNACHD</string>
+    <string name="pref_camera_focusmode_label_macro">MACRO</string>
+    <string name="pref_camera_flashmode_title">Modh an t-solais-bhoillsgidh</string>
+    <string name="pref_camera_flashmode_label">MODH an t-SOLAIS-BHOILLSGIDH</string>
+    <string name="pref_camera_flashmode_entry_auto">Fèin-obrachail</string>
+    <string name="pref_camera_flashmode_entry_on">Air</string>
+    <string name="pref_camera_flashmode_entry_off">Dheth</string>
+    <string name="pref_camera_flashmode_label_auto">SOLAS-BOILLSGIDH FÈIN-OBRACHAIL</string>
+    <string name="pref_camera_flashmode_label_on">SOLAS-BOILLSGIDH AIR</string>
+    <string name="pref_camera_flashmode_label_off">SOLAS-BOILLSGIDH DHETH</string>
+    <string name="pref_camera_whitebalance_title">Am balans geal</string>
+    <string name="pref_camera_whitebalance_label">AM BALANS GEAL</string>
+    <string name="pref_camera_whitebalance_entry_auto">Fèin-obrachail</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">Solas-dealain</string>
+    <string name="pref_camera_whitebalance_entry_daylight">Solas an latha</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">Fluaraiseach</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">Neulach</string>
+    <string name="pref_camera_whitebalance_label_auto">FÈIN-OBRACHAIL</string>
+    <string name="pref_camera_whitebalance_label_incandescent">SOLAS-DEALAIN</string>
+    <string name="pref_camera_whitebalance_label_daylight">SOLAS an LATHA</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">FLUARAISEACH</string>
+    <string name="pref_camera_whitebalance_label_cloudy">NEULACH</string>
+    <string name="pref_camera_scenemode_title">Am modh seallaidh</string>
+    <string name="pref_camera_scenemode_entry_auto">Fèin-obrachail</string>
+    <string name="pref_camera_scenemode_entry_hdr">HDR</string>
+    <string name="pref_camera_scenemode_entry_action">Gluasad</string>
+    <string name="pref_camera_scenemode_entry_night">Oidhche</string>
+    <string name="pref_camera_scenemode_entry_sunset">Laighe na grèine</string>
+    <string name="pref_camera_scenemode_entry_party">Cèilidh</string>
+    <string name="pref_camera_scenemode_label_auto">CHAN EIL GIN</string>
+    <string name="pref_camera_scenemode_label_action">GLUASAD</string>
+    <string name="pref_camera_scenemode_label_night">OIDHCHE</string>
+    <string name="pref_camera_scenemode_label_sunset">LAIGHE na GRÈINE</string>
+    <string name="pref_camera_scenemode_label_party">CÈILIDH</string>
+    <string name="pref_camera_countdown_label">TÌMEAR CUNNTAIDH SÌOS</string>
+    <string name="pref_camera_countdown_label_off">TÌMEAR DHETH</string>
+    <string name="pref_camera_countdown_label_one">1 DIOG</string>
+    <string name="pref_camera_countdown_label_three">3 DIOGAN</string>
+    <string name="pref_camera_countdown_label_ten">10 DIOGAN</string>
+    <string name="pref_camera_countdown_label_fifteen">15 DIOGAN</string>
+    <string name="not_selectable_in_scene_mode">Cha ghabh a thaghadh sa mhodh seallaidh.</string>
+    <string name="pref_exposure_title">Deisearas</string>
+    <string name="pref_exposure_label">DEISEARAS</string>
+    <string name="pref_camera_hdr_default">@string/setting_off_value</string>
+    <string name="pref_camera_hdr_label">HDR</string>
+    <string name="pref_camera_id_label_back">CAMARA BEÒIL</string>
+    <string name="pref_camera_id_label_front">CAMARA CÙIL</string>
+    <string name="dialog_ok">Ceart ma-thà</string>
+    <string name="spaceIsLow_content" product="nosdcard">Tha an stòras gu bhith a’ ruith air an stòras USB agad. Atharraich roghainn na càileachd no sguab às dealbh no dhà no faidhlichean eile.</string>
+    <string name="spaceIsLow_content" product="default">Tha an àite gu bhith a’ ruith air a’ chairt SD agad. Atharraich roghainn na càileachd no sguab às dealbh no dhà no faidhlichean eile.</string>
+    <string name="video_reach_size_limit">Ràinig thu crìoch a’ mheud.</string>
+    <string name="pano_too_fast_prompt">Ro luath</string>
+    <string name="pano_dialog_prepare_preview">Ag ullachadh a’ chuairt-sheallaidh</string>
+    <string name="pano_dialog_panorama_failed">Cha b’ urrainn dhuinn an cuairt-shealladh a shàbhaladh.</string>
+    <string name="pano_dialog_title">Cuairt-shealladh</string>
+    <string name="pano_capture_indication">A’ glacadh cuairt-shealladh</string>
+    <string name="pano_dialog_waiting_previous">A’ feitheamh ris a’ chuairt-shealladh roimhe</string>
+    <string name="pano_review_saving_indication_str">’Ga shàbhaladh\u2026</string>
+    <string name="pano_review_rendering">A’ reandaradh a’ chuairt-sheallaidh</string>
+    <string name="tap_to_focus">Suath ris airson fòcas.</string>
+    <string name="pref_video_effect_title">Èifeachdan</string>
+    <string name="effect_none">Chan eil gin</string>
+    <string name="effect_goofy_face_squeeze">Teannaich</string>
+    <string name="effect_goofy_face_big_eyes">Sùilean mòra</string>
+    <string name="effect_goofy_face_big_mouth">Beul mòr</string>
+    <string name="effect_goofy_face_small_mouth">Beul beag</string>
+    <string name="effect_goofy_face_big_nose">Sròn mhòr</string>
+    <string name="effect_goofy_face_small_eyes">Sùilean beaga</string>
+    <string name="effect_backdropper_space">San fhànas</string>
+    <string name="effect_backdropper_sunset">Laighe na grèine</string>
+    <string name="effect_backdropper_gallery">A’ video agad</string>
+    <string name="bg_replacement_message">Cuir an t-uidheam agad sìos.\nRach a-mach à sealladh greis.</string>
+    <string name="video_snapshot_hint">Suath ris airson dealbh a thogail rè a’ chlàraidh.</string>
+    <string name="video_recording_started">Thòisich clàradh a’ video.</string>
+    <string name="video_recording_stopped">Stad clàradh a’ video.</string>
+    <string name="disable_video_snapshot_hint">Tha snapshot video à comas fhad ’s a tha na h-èifeachdan sònraichte air.</string>
+    <string name="clear_effects">Falamhaich na h-èifeachdan</string>
+    <string name="effect_silly_faces">AODANNAN GÒRACH</string>
+    <string name="effect_background">CÙLAIBH</string>
+    <string name="accessibility_shutter_button">Putan an t-siutair</string>
+    <string name="accessibility_menu_button">Putan a’ chlàir-thaice</string>
+    <string name="accessibility_review_thumbnail">An dealbh as ùire</string>
+    <string name="accessibility_camera_picker">Geàrr leum eadar camara beòil ’s cùil</string>
+    <string name="accessibility_mode_picker">Taghadh a’ chamara, a’ video no a’ chuairt-sheallaidh</string>
+    <string name="accessibility_second_level_indicators">Barrachd uidheaman-smachd nan roghainnean</string>
+    <string name="accessibility_back_to_first_level">Dùin uidheaman-smachd nan roghainnean</string>
+    <string name="accessibility_zoom_control">Stiùir an t-sùm</string>
+    <string name="accessibility_decrement">Lùghdaich %1$s</string>
+    <string name="accessibility_increment">Meudaich %1$s</string>
+    <string name="accessibility_check_box">Bogsa-cromaige %1$s</string>
+    <string name="accessibility_switch_to_camera">Atharraich gu dealbh-camara</string>
+    <string name="accessibility_switch_to_video">Atharraich gu video</string>
+    <string name="accessibility_switch_to_panorama">Atharraich gu cuairt-shealladh</string>
+    <string name="accessibility_switch_to_new_panorama">Atharraich gu cuairt-shealladh ùr</string>
+    <string name="accessibility_switch_to_refocus">Atharraich gu ath-fhòcas</string>
+    <string name="accessibility_review_cancel">Sgrùdadh – Sguir dheth</string>
+    <string name="accessibility_review_ok">Sgrùdadh – Deiseil</string>
+    <string name="accessibility_review_retake">Sgrùdadh – Tog a-rithist e</string>
+    <string name="accessibility_play_video">Cluich a’ video</string>
+    <string name="accessibility_pause_video">Cuir a’ video ’na stad</string>
+    <string name="accessibility_reload_video">Ath-luchdaich a’ video</string>
+    <string name="accessibility_time_bar">Bàr ama a’ chluicheadair video</string>
+    <string name="capital_on">AIR</string>
+    <string name="capital_off">DHETH</string>
+    <string name="pref_video_time_lapse_frame_interval_off">Dheth</string>
+    <string name="pref_video_time_lapse_frame_interval_500">Leth-dhiog</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 diog</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">Diog gu leth</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 dhiog</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2 dhiog gu leth</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 dhiog</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 diogan</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 diog</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">Leth-mhionaid</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">Mionaid</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">Mionaid gu leth</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 mhionaid</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2 mhionaid gu leth</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 mhionaid</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 mionaidean</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 mionaid</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">Leth-uair a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 uair a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">Uair gu leth a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 uair a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2 uair gu leth a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 uair a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 uairean a thìde</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 uair a thìde</string>
+    <string name="time_lapse_seconds">diog</string>
+    <string name="time_lapse_minutes">mionaid</string>
+    <string name="time_lapse_hours">uair a thìde</string>
+    <string name="time_lapse_interval_set">Deiseil</string>
+    <string name="set_time_interval">Suidhich an t-eadaramh</string>
+    <string name="set_time_interval_help">Tha gleus an fhilm luathaichte dheth. Cuir air e airson eadaramh a shuidheachadh.</string>
+    <string name="set_timer_help">Tha an tìmear cunntaidh sìos dheth. Cuir air e airson cunntadh sìos mus dèid dealbh a thogail.</string>
+    <string name="set_duration">Suidhich an fhaid ann an diogan</string>
+    <string name="count_down_title_text">A’ cunntadh sìos airson dealbh a thogail</string>
+    <string name="remember_location_title">An cuimhnich sinn ionadan nan dealbh dhut?</string>
+    <string name="remember_location_prompt">Cuir tagaichean ris na dealbhan is videothan agad leis na h-ionadan far an deach an togail.\n\nGheibh aplacaidean eile cothrom air an fhiosrachadh seo cuide ris na dealbhan a shàbhail thu.</string>
+    <string name="remember_location_no">Cha chuimhnich</string>
+    <string name="remember_location_yes">Cuimhnichidh</string>
+    <string name="menu_camera">Camara</string>
+    <string name="menu_search">Lorg</string>
+    <string name="tab_photos">Dealbhan</string>
+    <string name="tab_albums">Albaman</string>
+    <string name="camera_menu_more_label">BARRACHD ROGHAINNEAN</string>
+    <string name="camera_menu_settings_label">ROGHAINNEAN</string>
+    <plurals name="number_of_photos">
+        <item quantity="one">%1$d dealbh</item>
+        <item quantity="two">%1$d dhealbh</item>
+        <item quantity="few">%1$d dealbhan</item>
+        <item quantity="other">%1$d dealbh</item>
+    </plurals>
+</resources>
diff --git a/res/values-gl/cm_strings.xml b/res/values-gl/cm_strings.xml
new file mode 100644
index 0000000..22b1fd7
--- /dev/null
+++ b/res/values-gl/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Data da gravación</string>
+</resources>
diff --git a/res/values-gl/codeaurora_strings.xml b/res/values-gl/codeaurora_strings.xml
new file mode 100644
index 0000000..6206979
--- /dev/null
+++ b/res/values-gl/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Etapa</string>
+    <string name="step_option_desc">Personalizar a velocidade de avance/retroceso</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Bucle"</string>
+    <string name="single">"Único"</string>
+    <string name="stereo">"Estéreo"</string>
+    <string name="speaker_on">Altofalante aceso</string>
+    <string name="speaker_off">Altofalante apagado</string>
+    <string name="speaker_need_headset">Enchufar os auriculares para empregar esta funcionalidade.</string>
+    <string name="single_track">"Pista única"</string>
+    <string name="input_url">"Escribir o URL"</string>
+    <string name="streaming_settings">"Configuración de fluxo"</string>
+    <string name="next">"Seguinte"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamaño do búfer</string>
+    <string name="apn">APN favorito</string>
+    <string name="rtp_min_port">Porto mín.</string>
+    <string name="rtp_max_port">Porto máx.</string>
+    <string name="set_rtp_min_port">Estabelecer porto mín.</string>
+    <string name="set_rtp_max_port">Estabelecer porto máx.</string>
+    <string name="set_buffer_size">Estabelecer tamaño do búfer</string>
+    <string name="set_apn">Seleccionar o APN favorito</string>
+    <string name="setting">Configuración</string>
+    <string name="server_timeout_title">"Tempo de espera do servidor"</string>
+    <string name="server_timeout_message">"Reconectar co servidor para reproducir o vídeo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Fallou a conexión, tentarase reconectar con %1$d\u2026"</string>
+    <string name="media_controller_live">Ao vivo</string>
+    <string name="media_controller_playing">Reproducindo</string>
+    <string name="media_controller_connecting">Conectando\u2026</string>
+    <string name="bookmark_add">"Engadir marcador"</string>
+    <string name="bookmark_display">"Amosar os marcadores"</string>
+    <string name="bookmark_empty">"Sen marcadores"</string>
+    <string name="bookmark_exist">"O marcador xa existe"</string>
+    <string name="bookmark_add_success">"Marcador engadido"</string>
+    <string name="bookmark_list">"Marcadores"</string>
+    <string name="bookmark_title">"Título"</string>
+    <string name="bookmark_location">"Localización"</string>
+    <string name="delete_all">"Eliminar todo"</string>
+    <string name="default_title">"Título predeterminado"</string>
+    <string name="more_image">Máis imaxes</string>
+    <string name="mute_nosupport">Non se pode silenciar: vídeo non compatíbel</string>
+    <string name="map_activity_not_found_err">Non hai unha aplicación de mapas para amosar a localización.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vídeo</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">O máximo de elemento a compartir é de 300</string>
+    <string name="share_dialogue_title">Compartir vía</string>
+    <string name="no_faces">Sen faces</string>
+    <string name="fail_trim">Vaia, o vídeo non se pode recortar</string>
+    <string name="can_not_trim">Só os ficheiros mp4 e 3gp poden ser recortados</string>
+    <string name="drm_license_info">Información da licenza DRM</string>
+    <string name="timeline_title">Cronoloxía</string>
+    <string name="albums_title">Álbums</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Vista en lista</string>
+    <string name="tvEmptyAlbum">Non se atoparon fotos</string>
+    <string name="tvEmptyVideos">Non se atoparon vídeos</string>
+    <string name="text_makeup_whiten">Branquear</string>
+    <string name="text_makeup_Soften">Suavizar</string>
+    <string name="text_makeup_trimface">Retoque facial</string>
+    <string name="text_makeup_bigeye">Ollos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Encerado branco</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Eliminar reflexos</string>
+    <string name="hazebuster_acts">Axuste de brétema</string>
+    <string name="seestraight_acts">Ver directamente</string>
+    <string name="seestraight_input_image_is_small">A imaxe é pequena de máis para procesar.</string>
+    <string name="seestraight_process_fail">Non foi posíbel procesar a imaxe.</string>
+    <string name="trim_video_exit_title">Desbotar cambios?</string>
+    <string name="trim_video_exit_msg">Desbotar os cambios feitos no vídeo?</string>
+    <string name="trim_video_exit_discard">DESBOTAR</string>
+</resources>
diff --git a/res/values-gu/cm_strings.xml b/res/values-gu/cm_strings.xml
new file mode 100644
index 0000000..9f43675
--- /dev/null
+++ b/res/values-gu/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">સમય રેકોર્ડ કરો</string>
+</resources>
diff --git a/res/values-gu/codeaurora_strings.xml b/res/values-gu/codeaurora_strings.xml
new file mode 100644
index 0000000..3b23b0b
--- /dev/null
+++ b/res/values-gu/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">પગલાં</string>
+    <string name="step_option_desc">ફાસ્ટ ફોરવર્ડ/રિવાઇન્ડ પગલાંને કસ્ટમાઇઝ કરો</string>
+    <string name="setp_option_three_second">3 સેકન્ડ્સ</string>
+    <string name="setp_option_six_second">6 સેકન્ડ્સ</string>
+    <string name="loop">""લુપ""</string>
+    <string name="single">""એકલ""</string>
+    <string name="stereo">""સ્ટીરીયો""</string>
+    <string name="speaker_on">સ્પિકર ON</string>
+    <string name="speaker_off">સ્પિકર OFF</string>
+    <string name="speaker_need_headset">આ ફીચરનો ઉપયોગ કરવા હેડફોન પ્લગ ઇન કરો.</string>
+    <string name="single_track">""એકલ ટ્રેક""</string>
+    <string name="input_url">""Enter URL""</string>
+    <string name="streaming_settings">""Streaming settings""</string>
+    <string name="next">""આગામી""</string>
+    <string name="previous">""પાછળ""</string>
+    <string name="buffer_size">બફર સાઇઝ</string>
+    <string name="apn">પસંદગીનું APN</string>
+    <string name="rtp_min_port">મીન પોર્ટ</string>
+    <string name="rtp_max_port">મેક્સ પોર્ટ</string>
+    <string name="set_rtp_min_port">મીન પોર્ટ સેટ કરો</string>
+    <string name="set_rtp_max_port">મેક્સ પોર્ટ સેટ કરો</string>
+    <string name="set_buffer_size">સેટ બફર માપ</string>
+    <string name="set_apn">APN પસંદ કરો</string>
+    <string name="setting">સેટિંગ્સ</string>
+    <string name="server_timeout_title">""સર્વર ટાઇમઆઉટ""</string>
+    <string name="server_timeout_message">""શું વીડિયો પ્લે કરવા સર્વર સાથે રિકનેક્ટ કરવું છે?""</string>
+    <string name="videoview_error_text_cannot_connect_retry">""કનેકશન નિષ્ફળ, %1$d\u2026 સાથે રિકનેક્ટ કરવાનો પ્રયાસ કરીએ છીએ""</string>
+    <string name="media_controller_live">જીવંત</string>
+    <string name="media_controller_playing">રમી</string>
+    <string name="media_controller_connecting">કનેક્ટ થઈ રહ્યું છે…</string>
+    <string name="bookmark_add">""બુકમાર્ક ઉમેરો""</string>
+    <string name="bookmark_display">""બુકમાર્ક્સ દર્શાવો""</string>
+    <string name="bookmark_empty">""કોઇ બુકમાર્ક્સ નથી""</string>
+    <string name="bookmark_exist">""બુકમાર્ક અગાઉથી હાજર છે""</string>
+    <string name="bookmark_add_success">""બુકમાર્ક ઉમેરવામાં આવ્યું""</string>
+    <string name="bookmark_list">""બુકમાર્ક્સ""</string>
+    <string name="bookmark_title">""શીર્ષક""</string>
+    <string name="bookmark_location">""સ્થાન""</string>
+    <string name="delete_all">""તમામ હટાવો""</string>
+    <string name="default_title">""મૂળભૂત શીર્ષક""</string>
+    <string name="more_image">વધુ ચિત્રો</string>
+    <string name="mute_nosupport">મ્યૂટ ન થઈ શકે : વિડિયોને સમર્થન નથી</string>
+    <string name="map_activity_not_found_err">સ્થાન દર્શાવવા માટે કોઇ મૅપ્સ એપ્લિકેશન ઇન્સ્ટૉલ થયેલ નથી.</string>
+    <string name="fail_trim">માફ કરશો, આ વિડિયો ફાઇલ ટ્રિમ નહીં થઈ શકે</string>
+    <string name="drm_license_info">DRM લાયસન્સ ઇન્ફો</string>
+</resources>
diff --git a/res/values-hi/cm_strings.xml b/res/values-hi/cm_strings.xml
new file mode 100644
index 0000000..57d8058
--- /dev/null
+++ b/res/values-hi/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">रिकॉर्ड करने का समय</string>
+</resources>
diff --git a/res/values-hi/codeaurora_strings.xml b/res/values-hi/codeaurora_strings.xml
new file mode 100644
index 0000000..fcdc112
--- /dev/null
+++ b/res/values-hi/codeaurora_strings.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">चरण</string>
+    <string name="step_option_desc">फ़ास्ट फॉरवर्ड/रीवाइंड चरण को मनपसंद बनाएँ</string>
+    <string name="setp_option_three_second">3 सेकंड</string>
+    <string name="setp_option_six_second">6 सेकंड</string>
+    <string name="loop">"लूप"</string>
+    <string name="single">"एकल"</string>
+    <string name="stereo">"स्टीरियो"</string>
+    <string name="speaker_on">स्पीकर चालू</string>
+    <string name="speaker_off">स्पीकर बंद</string>
+    <string name="speaker_need_headset">इस सुविधा का उपयोग करने के लिए हेडफ़ोन लगाएँ।</string>
+    <string name="single_track">"एकल ट्रैक"</string>
+    <string name="input_url">"यूआरएल दर्ज करें"</string>
+    <string name="streaming_settings">"स्ट्रीमिंग सेटिंग"</string>
+    <string name="next">"अगला"</string>
+    <string name="previous">"पिछला"</string>
+    <string name="buffer_size">बफ़र आमाप</string>
+    <string name="apn">पसंदीदा एपीएन</string>
+    <string name="rtp_min_port">न्यूनतम पोर्ट</string>
+    <string name="rtp_max_port">अधिकतम पोर्ट</string>
+    <string name="set_rtp_min_port">न्यूनतम पोर्ट सेट करें</string>
+    <string name="set_rtp_max_port">अधिकतम पोर्ट सेट करें</string>
+    <string name="set_buffer_size">बफ़र आमाप सेट करें</string>
+    <string name="set_apn">पसंदीदा एपीएन चुनें</string>
+    <string name="setting">सेटिंग</string>
+    <string name="server_timeout_title">"सर्वर समय समाप्त"</string>
+    <string name="server_timeout_message">"वीडियो बजाने के लिए सर्वर के साथ फिर से जुड़ जाएँ?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"कनेक्शन विफल हुआ। %1$d के साथ फिर से कनेक्ट करने की कोशिश कर रहे हैं\u2026"</string>
+    <string name="media_controller_live">सजीव</string>
+    <string name="media_controller_playing">बजा रहे हैं</string>
+    <string name="media_controller_connecting">कनेक्ट कर रहे हैं\u2026</string>
+    <string name="bookmark_add">"बुकमार्क जोड़ें"</string>
+    <string name="bookmark_display">"बुकमार्क दिखाएँ"</string>
+    <string name="bookmark_empty">"कोई बुकमार्क नहीं"</string>
+    <string name="bookmark_exist">"बुकमार्क पहले से ही मौजूद है"</string>
+    <string name="bookmark_add_success">"बुकमार्क जोड़ा गया"</string>
+    <string name="bookmark_list">"बुकमार्क"</string>
+    <string name="bookmark_title">"शीर्षक"</string>
+    <string name="bookmark_location">"स्थान"</string>
+    <string name="delete_all">"सब हटाएँ"</string>
+    <string name="default_title">"डिफ़ॉल्ट शीर्षक"</string>
+    <string name="more_image">और छवियाँ</string>
+    <string name="mute_nosupport">मूक नहीं कर सके : वीडियो समर्थित नहीं है</string>
+    <string name="map_activity_not_found_err">स्थान दर्शाने के लिए कोई नक्शा ऐप स्थापित नहीं है।</string>
+    <string name="fail_trim">क्षमा करें, इस वीडियो फ़ाइल को ट्रिम नहीं कर सकते</string>
+</resources>
diff --git a/res/values-hr/cm_strings.xml b/res/values-hr/cm_strings.xml
new file mode 100644
index 0000000..4cfc981
--- /dev/null
+++ b/res/values-hr/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Trajanje snimke</string>
+</resources>
diff --git a/res/values-hr/codeaurora_strings.xml b/res/values-hr/codeaurora_strings.xml
new file mode 100644
index 0000000..fe04936
--- /dev/null
+++ b/res/values-hr/codeaurora_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Korak</string>
+    <string name="step_option_desc">Prilagodite korak ubrzanja/premotavanja</string>
+    <string name="setp_option_three_second">3 sekunde</string>
+    <string name="setp_option_six_second">6 sekundi</string>
+    <string name="loop">"Ponavljanje"</string>
+    <string name="single">"Pojedinačna"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Zvučnik UKLJUČEN</string>
+    <string name="speaker_off">Zvučnik ISKLJUČEN</string>
+    <string name="speaker_need_headset">Priključite slušalice za korištenje ove mogućnosti.</string>
+    <string name="single_track">"Jedna pjesma"</string>
+    <string name="input_url">"Unesite URL"</string>
+    <string name="streaming_settings">"Postavke strujanja"</string>
+    <string name="next">"Sljedeći"</string>
+    <string name="previous">"Prethodni"</string>
+    <string name="buffer_size">Veličina međuspremnika</string>
+    <string name="apn">Preferirani APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Postavi min port</string>
+    <string name="set_rtp_max_port">Postaviti max port</string>
+    <string name="set_buffer_size">Postavi veličinu međuspremnika</string>
+    <string name="set_apn">Odaberite željeni APN</string>
+    <string name="setting">Postavke</string>
+    <string name="server_timeout_title">"Isteklo vremensko ograničenje poslužitelja"</string>
+    <string name="server_timeout_message">"Ponovno se povezati sa poslužiteljem za pokretanje videozapisa?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Povezivanje nije uspjelo, ponovno povezivanje sa %1$d\u2026"</string>
+    <string name="media_controller_live">Uživo</string>
+    <string name="media_controller_playing">Reproduciranje</string>
+    <string name="media_controller_connecting">Spajanje\u2026</string>
+    <string name="bookmark_add">"Dodaj oznaku"</string>
+    <string name="bookmark_display">"Pokaži oznake"</string>
+    <string name="bookmark_empty">"Nema oznake"</string>
+    <string name="bookmark_exist">"Oznaka već postoji"</string>
+    <string name="bookmark_add_success">"Oznaka dodana"</string>
+    <string name="bookmark_list">"Oznake"</string>
+    <string name="bookmark_title">"Naslov"</string>
+    <string name="bookmark_location">"Lokacija"</string>
+    <string name="delete_all">"Izbriši sve"</string>
+    <string name="default_title">"Zadani naslov"</string>
+    <string name="more_image">Više slika</string>
+    <string name="mute_nosupport">Nije moguće isključiti zvuk: videozapis nije podržan</string>
+    <string name="map_activity_not_found_err">Nema instaliranih aplikacija karata za prikaz lokacije.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d videozapis</item>
+        <item quantity="few">%1$d videozapisa</item>
+        <item quantity="other">%1$d videozapisa</item>
+    </plurals>
+    <string name="cannot_share_items">Maks. broj odabranih stavki za zajedničko korištenje je 300</string>
+    <string name="share_dialogue_title">Dijeli putem</string>
+    <string name="no_faces">Nema lica</string>
+    <string name="fail_trim">Oprostite, ovaj video ne može biti izrezan</string>
+    <string name="can_not_trim">Samo mp4 i 3gp datoteke mogu biti izrezane</string>
+    <string name="drm_license_info">Informacije DRM licence</string>
+    <string name="timeline_title">Vremenska crta</string>
+    <string name="albums_title">Albumi</string>
+    <string name="videos_title">Videozapisi</string>
+    <string name="action_viewtype_list">Prikaz popisa</string>
+    <string name="tvEmptyAlbum">Nema pronađenih fotografija</string>
+    <string name="tvEmptyVideos">Nema pronađenih videozapisa</string>
+    <string name="text_makeup_whiten">Izbjeljivanje</string>
+    <string name="text_makeup_Soften">Omekšavanje</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Veliko oko</string>
+    <string name="truescanner_normal">Normalno</string>
+    <string name="truescanner_white">Bijela ploča</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Ukloni odbljesak</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Unesena slika je premala za obradu.</string>
+    <string name="seestraight_process_fail">Ne mogu obraditi sliku.</string>
+    <string name="trim_video_exit_title">Želite li odbaciti promjene?</string>
+    <string name="trim_video_exit_msg">Odbaciti promjene za ovaj videozapis?</string>
+    <string name="trim_video_exit_discard">ODBACI</string>
+</resources>
diff --git a/res/values-hu/cm_strings.xml b/res/values-hu/cm_strings.xml
new file mode 100644
index 0000000..63c8a35
--- /dev/null
+++ b/res/values-hu/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Felvétel ideje</string>
+</resources>
diff --git a/res/values-hu/codeaurora_strings.xml b/res/values-hu/codeaurora_strings.xml
new file mode 100644
index 0000000..966bf51
--- /dev/null
+++ b/res/values-hu/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Lépés</string>
+    <string name="step_option_desc">Gyors előre-/hátralépés testreszabása</string>
+    <string name="setp_option_three_second">3 másodperc</string>
+    <string name="setp_option_six_second">6 másodperc</string>
+    <string name="loop">"Ismétlés"</string>
+    <string name="single">"Egyszerű"</string>
+    <string name="stereo">"Sztereó"</string>
+    <string name="speaker_on">Hangszóró BE</string>
+    <string name="speaker_off">Hangszóró KI</string>
+    <string name="speaker_need_headset">Ezen funkció használatához csatlakoztasson fejhallgatót.</string>
+    <string name="single_track">"Egyetlen szám"</string>
+    <string name="input_url">"URL megadása"</string>
+    <string name="streaming_settings">"Műsorszórás beállításai"</string>
+    <string name="next">"Következő"</string>
+    <string name="previous">"Előző"</string>
+    <string name="buffer_size">Bufferméret</string>
+    <string name="apn">Előnyben részesített APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Min port beállítása</string>
+    <string name="set_rtp_max_port">Max port beállítása</string>
+    <string name="set_buffer_size">Pufferméret beállítása</string>
+    <string name="set_apn">Válassza ki a kívánt APN-t</string>
+    <string name="setting">Beállítások</string>
+    <string name="server_timeout_title">"Kiszolgálói időtúllépés"</string>
+    <string name="server_timeout_message">"Újracsatlakozzon a szerverhez a videó lejátszásához?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Sikertelen csatlakozás, újracsatlakozási kísérlet a következőhöz: %1$d\u2026"</string>
+    <string name="media_controller_live">Élő</string>
+    <string name="media_controller_playing">Lejátszás</string>
+    <string name="media_controller_connecting">Csatlakozás\u2026</string>
+    <string name="bookmark_add">"Könyvjelző hozzáadása"</string>
+    <string name="bookmark_display">"Könyvjelzők megjelenítése"</string>
+    <string name="bookmark_empty">"Nincs könyvjelző"</string>
+    <string name="bookmark_exist">"Könyvjelző már létezik"</string>
+    <string name="bookmark_add_success">"Könyvjelző hozzáadva"</string>
+    <string name="bookmark_list">"Könyvjelzők"</string>
+    <string name="bookmark_title">"Név"</string>
+    <string name="bookmark_location">"Hely"</string>
+    <string name="delete_all">"Összes törlése"</string>
+    <string name="default_title">"Alapértelmezett név"</string>
+    <string name="more_image">További képek</string>
+    <string name="mute_nosupport">Nem némítható: videó nem támogatott</string>
+    <string name="map_activity_not_found_err">Nincs telepítve térkép alkalmazás a hely megjelenítéséhez.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d videó</item>
+        <item quantity="other">%1$d videó</item>
+    </plurals>
+    <string name="cannot_share_items">Max 300 kijelölt elem osztható meg</string>
+    <string name="share_dialogue_title">Megosztás a következővel:</string>
+    <string name="no_faces">Nincsenek arcok</string>
+    <string name="fail_trim">Sajnáljuk, de ez a videófájl nem vágható</string>
+    <string name="can_not_trim">Csak mp4 és 3gp fájlokat lehet vágni</string>
+    <string name="drm_license_info">DRM liszensz információ</string>
+    <string name="timeline_title">Idővonal</string>
+    <string name="albums_title">Albumok</string>
+    <string name="videos_title">Videók</string>
+    <string name="action_viewtype_list">Lista nézet</string>
+    <string name="tvEmptyAlbum">Nem találhatóak képek</string>
+    <string name="tvEmptyVideos">Nem találhatóak videók</string>
+    <string name="text_makeup_whiten">Fehérítés</string>
+    <string name="text_makeup_Soften">Lágyítás</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Nagyszemű</string>
+    <string name="truescanner_normal">Normál</string>
+    <string name="truescanner_white">Fehértábla</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Ragyogás eltávolítása</string>
+    <string name="hazebuster_acts">Homályosságszűrő</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Bemeneti kép túl kicsi a feldolgozáshoz.</string>
+    <string name="seestraight_process_fail">Nem sikerült feldolgozni a képet.</string>
+    <string name="trim_video_exit_title">Elveti a változtatásokat?</string>
+    <string name="trim_video_exit_msg">Elveti a videón végzett változtatásokat?</string>
+    <string name="trim_video_exit_discard">ELVETÉS</string>
+</resources>
diff --git a/res/values-in/cm_strings.xml b/res/values-in/cm_strings.xml
new file mode 100644
index 0000000..d7ac5f0
--- /dev/null
+++ b/res/values-in/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Waktu rekaman</string>
+</resources>
diff --git a/res/values-in/codeaurora_strings.xml b/res/values-in/codeaurora_strings.xml
new file mode 100644
index 0000000..eb551cd
--- /dev/null
+++ b/res/values-in/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Langkah</string>
+    <string name="step_option_desc">Sesuaikan tahap maju cepat/mundur</string>
+    <string name="setp_option_three_second">3 detik</string>
+    <string name="setp_option_six_second">6 detik</string>
+    <string name="loop">"Ulang"</string>
+    <string name="single">"Tunggal"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker HIDUP</string>
+    <string name="speaker_off">Speaker MATI</string>
+    <string name="speaker_need_headset">Pasang headphone untuk menggunakan fitur ini.</string>
+    <string name="single_track">"Trek tunggal"</string>
+    <string name="input_url">"Masukkan URL"</string>
+    <string name="streaming_settings">"Pengaturan streaming"</string>
+    <string name="next">"Berikutnya"</string>
+    <string name="previous">"Sebelumnya"</string>
+    <string name="buffer_size">Ukuran buffer</string>
+    <string name="apn">Pilihan APN</string>
+    <string name="rtp_min_port">Port min</string>
+    <string name="rtp_max_port">Port maks</string>
+    <string name="set_rtp_min_port">Atur porta min</string>
+    <string name="set_rtp_max_port">Atur porta maks</string>
+    <string name="set_buffer_size">Atur ukuran buffer</string>
+    <string name="set_apn">Pilih pilihan APN</string>
+    <string name="setting">Pengaturan</string>
+    <string name="server_timeout_title">"Batas waktu server"</string>
+    <string name="server_timeout_message">"Menyambung ulang ke server untuk memutar video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Koneksi gagal, mencoba untuk menyambung ulang ke %1$d\u2026"</string>
+    <string name="media_controller_live">Langsung</string>
+    <string name="media_controller_playing">Memutar</string>
+    <string name="media_controller_connecting">Menyambungkan\u2026</string>
+    <string name="bookmark_add">"Tambah ke bookmark"</string>
+    <string name="bookmark_display">"Tampilkan bookmark"</string>
+    <string name="bookmark_empty">"Tidak ada bookmark"</string>
+    <string name="bookmark_exist">"Bookmark sudah ada"</string>
+    <string name="bookmark_add_success">"Bookmark ditambahkan"</string>
+    <string name="bookmark_list">"Bookmark"</string>
+    <string name="bookmark_title">"Judul"</string>
+    <string name="bookmark_location">"Lokasi"</string>
+    <string name="delete_all">"Hapus semua"</string>
+    <string name="default_title">"Judul standar"</string>
+    <string name="more_image">Lebih banyak gambar</string>
+    <string name="mute_nosupport">Tidak dapat mendiamkan : video tidak didukung</string>
+    <string name="map_activity_not_found_err">Tidak ada aplikasi peta yang diinstal untuk menunjukkan lokasi.</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Item dipilih untuk dibagikan maksimal 300 item</string>
+    <string name="share_dialogue_title">Bagikan lewat</string>
+    <string name="no_faces">Tidak ada wajah</string>
+    <string name="fail_trim">Maaf, berkas video ini tidak dapat dipotong</string>
+    <string name="can_not_trim">Hanya berkas mp4 dan 3gp yang dapat dipotong</string>
+    <string name="drm_license_info">Info lisensi DRM</string>
+    <string name="timeline_title">Berita terbaru</string>
+    <string name="albums_title">Album</string>
+    <string name="videos_title">Video</string>
+    <string name="action_viewtype_list">Tampilan daftar</string>
+    <string name="tvEmptyAlbum">Tidak ada foto ditemukan</string>
+    <string name="tvEmptyVideos">Tidak ada video ditemukan</string>
+    <string name="text_makeup_whiten">Putihkan</string>
+    <string name="text_makeup_Soften">Perhalus</string>
+    <string name="text_makeup_trimface">Mempercantik wajah</string>
+    <string name="text_makeup_bigeye">Mata besar</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Papan tulis putih</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Hapus kilauan</string>
+    <string name="hazebuster_acts">Pembasmi Kabut</string>
+    <string name="seestraight_acts">Melihat lurus</string>
+    <string name="seestraight_input_image_is_small">Gambar masukan terlalu kecil untuk diproses.</string>
+    <string name="seestraight_process_fail">Tidak dapat memproses gambar.</string>
+    <string name="trim_video_exit_title">Batalkan perubahan?</string>
+    <string name="trim_video_exit_msg">Buang perubahan yang dibuat untuk video ini?</string>
+    <string name="trim_video_exit_discard">BUANG</string>
+</resources>
diff --git a/res/values-is/cm_strings.xml b/res/values-is/cm_strings.xml
new file mode 100644
index 0000000..b5d1212
--- /dev/null
+++ b/res/values-is/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tímalengd upptöku</string>
+</resources>
diff --git a/res/values-is/codeaurora_strings.xml b/res/values-is/codeaurora_strings.xml
new file mode 100644
index 0000000..f5b256c
--- /dev/null
+++ b/res/values-is/codeaurora_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Skref</string>
+    <string name="step_option_desc">Sérsníða þrepun í Áfram/Til baka</string>
+    <string name="single">"Einu sinni"</string>
+    <string name="single_track">"Eitt lag"</string>
+    <string name="apn">Forgangs-APN</string>
+    <string name="rtp_min_port">Lágmarksgátt</string>
+    <string name="rtp_max_port">Hámarksgátt</string>
+    <string name="set_rtp_min_port">Setja lágmarksgátt</string>
+    <string name="set_rtp_max_port">Setja hámarksgátt</string>
+    <string name="set_buffer_size">Setja stærð biðminnis</string>
+    <string name="set_apn">Veldu APN í forgangi</string>
+    <string name="server_timeout_title">"Þjónn rann út á tíma"</string>
+    <string name="server_timeout_message">"Tengjast þjóninum aftur til að spila myndskeiðið?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Tengingin brást, reyni aftur að tengjast við %1$d\u2026"</string>
+    <string name="default_title">"Sjálfgefinn titill"</string>
+    <string name="more_image">Fleiri myndir</string>
+    <string name="map_activity_not_found_err">Ekkert kortaforrit er uppsett sem gæti sýnt staðsetninguna.</string>
+    <string name="cannot_share_items">Hámarksfjöldi valinna atriða fyrir deilingu er 300</string>
+    <string name="fail_trim">Því miður, það er ekki hægt að skera af þessari myndskeiðsskrá</string>
+    <string name="drm_license_info">Upplýsingar um DRM-notkunarleyfi</string>
+    <string name="albums_title">Hljómplötur</string>
+    <string name="seestraight_input_image_is_small">Inntaksmynd er of lítil til að vinna með hana.</string>
+    <string name="seestraight_process_fail">Gat ekki unnið með myndina.</string>
+    <string name="trim_video_exit_msg">Henda þeim breytingum sem gerðar hafa verið á þessu myndskeiði?</string>
+</resources>
diff --git a/res/values-it/cm_strings.xml b/res/values-it/cm_strings.xml
new file mode 100644
index 0000000..0aca54f
--- /dev/null
+++ b/res/values-it/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tempo di ripresa</string>
+</resources>
diff --git a/res/values-it/codeaurora_strings.xml b/res/values-it/codeaurora_strings.xml
new file mode 100644
index 0000000..b81adec
--- /dev/null
+++ b/res/values-it/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Passo</string>
+    <string name="step_option_desc">Personalizza l\'avanzamento/riavvolgimento rapido</string>
+    <string name="setp_option_three_second">3 secondi</string>
+    <string name="setp_option_six_second">6 secondi</string>
+    <string name="loop">"Ripeti"</string>
+    <string name="single">"Singolo"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Altoparlante ON</string>
+    <string name="speaker_off">Altoparlante OFF</string>
+    <string name="speaker_need_headset">Inserisci gli auricolari per utilizzare questa funzionalità.</string>
+    <string name="single_track">"Traccia singola"</string>
+    <string name="input_url">"Inserisci URL"</string>
+    <string name="streaming_settings">"Impostazioni streaming"</string>
+    <string name="next">"Successivo"</string>
+    <string name="previous">"Precedente"</string>
+    <string name="buffer_size">Dimensione buffer</string>
+    <string name="apn">APN preferito</string>
+    <string name="rtp_min_port">Porta min</string>
+    <string name="rtp_max_port">Porta max</string>
+    <string name="set_rtp_min_port">Imposta porta min</string>
+    <string name="set_rtp_max_port">Imposta porta max</string>
+    <string name="set_buffer_size">Imposta dimensione del buffer</string>
+    <string name="set_apn">Imposta APN preferito</string>
+    <string name="setting">Impostazioni</string>
+    <string name="server_timeout_title">"Timeout del server"</string>
+    <string name="server_timeout_message">"Riconnettersi al server per riprodurre il video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connessione fallita, provando a riconnettersi a %1$d\u2026"</string>
+    <string name="media_controller_live">Dal vivo</string>
+    <string name="media_controller_playing">In riproduzione</string>
+    <string name="media_controller_connecting">Connessione\u2026</string>
+    <string name="bookmark_add">"Aggiungi segnalibro"</string>
+    <string name="bookmark_display">"Visualizza segnalibri"</string>
+    <string name="bookmark_empty">"Nessun segnalibro"</string>
+    <string name="bookmark_exist">"Il segnalibro esiste già"</string>
+    <string name="bookmark_add_success">"Segnalibro aggiunto"</string>
+    <string name="bookmark_list">"Segnalibri"</string>
+    <string name="bookmark_title">"Titolo"</string>
+    <string name="bookmark_location">"Posizione"</string>
+    <string name="delete_all">"Elimina tutto"</string>
+    <string name="default_title">"Titolo predefinito"</string>
+    <string name="more_image">Altre immagini</string>
+    <string name="mute_nosupport">Impossibile disattivare l\'audio: video non supportato</string>
+    <string name="map_activity_not_found_err">Non non c\'è nessuna app mappe installata per mostrare la posizione.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Il numero massimo di elementi condivisibili è 300</string>
+    <string name="share_dialogue_title">Condividi con</string>
+    <string name="no_faces">Nessun volto</string>
+    <string name="fail_trim">Questo file video non può essere tagliato</string>
+    <string name="can_not_trim">Solo i file mp4 e 3gp possono essere tagliati</string>
+    <string name="drm_license_info">Info licenza DRM</string>
+    <string name="timeline_title">Ricordi</string>
+    <string name="albums_title">Album</string>
+    <string name="videos_title">Video</string>
+    <string name="action_viewtype_list">Vista elenco</string>
+    <string name="tvEmptyAlbum">Nessuna foto trovata</string>
+    <string name="tvEmptyVideos">Nessun video trovato</string>
+    <string name="text_makeup_whiten">Bianchi</string>
+    <string name="text_makeup_Soften">Soft</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Occhi grandi</string>
+    <string name="truescanner_normal">Normale</string>
+    <string name="truescanner_white">Lavagna bianca</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Rimuovi bagliore</string>
+    <string name="hazebuster_acts">Rimuovi foschia</string>
+    <string name="seestraight_acts">Vista diretta</string>
+    <string name="seestraight_input_image_is_small">L\'immagine è troppo piccola per essere elaborata.</string>
+    <string name="seestraight_process_fail">Impossibile elaborare l\'immagine.</string>
+    <string name="trim_video_exit_title">Annullare le modifiche?</string>
+    <string name="trim_video_exit_msg">Annullare le modifiche apportate a questo video?</string>
+    <string name="trim_video_exit_discard">ANNULLA</string>
+</resources>
diff --git a/res/values-iw/cm_strings.xml b/res/values-iw/cm_strings.xml
new file mode 100644
index 0000000..2c370a4
--- /dev/null
+++ b/res/values-iw/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">זמן הקלטה</string>
+</resources>
diff --git a/res/values-iw/codeaurora_strings.xml b/res/values-iw/codeaurora_strings.xml
new file mode 100644
index 0000000..f4dbf72
--- /dev/null
+++ b/res/values-iw/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">דילוג</string>
+    <string name="step_option_desc">התאם אישית דילוג מהיר קדימה/אחורה</string>
+    <string name="setp_option_three_second">3 שניות</string>
+    <string name="setp_option_six_second">6 שניות</string>
+    <string name="loop">"לולאה"</string>
+    <string name="single">"יחיד"</string>
+    <string name="stereo">"סטריאו"</string>
+    <string name="speaker_on">רמקול פעיל</string>
+    <string name="speaker_off">רמקול כבוי</string>
+    <string name="speaker_need_headset">חבר אזניות כדי להשתמש בתכונה זו.</string>
+    <string name="single_track">"רצועה יחידה"</string>
+    <string name="input_url">"הזן כתובת URL"</string>
+    <string name="streaming_settings">"הגדרות הזרמה"</string>
+    <string name="next">"הבא"</string>
+    <string name="previous">"הקודם"</string>
+    <string name="buffer_size">גודל המאגר</string>
+    <string name="apn">APN מועדף</string>
+    <string name="rtp_min_port">פורט מינימאלי</string>
+    <string name="rtp_max_port">פורט מקסימלי</string>
+    <string name="set_rtp_min_port">הגדר פורט מינימלי</string>
+    <string name="set_rtp_max_port">הגדר פורט מקסימלי</string>
+    <string name="set_buffer_size">הגדר גודל מאגר</string>
+    <string name="set_apn">בחר APN מועדף</string>
+    <string name="setting">הגדרות</string>
+    <string name="server_timeout_title">"זמן קצוב לשרת"</string>
+    <string name="server_timeout_message">"להתחבר מחדש לשרת כדי להפעיל את הווידאו?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"החיבור נכשל, מנסה להתחבר מחדש ל- %1$d\u2026"</string>
+    <string name="media_controller_live">חי</string>
+    <string name="media_controller_playing">מנגן</string>
+    <string name="media_controller_connecting">מתחבר\u2026</string>
+    <string name="bookmark_add">"הוסף סימניה"</string>
+    <string name="bookmark_display">"הצג סימניות"</string>
+    <string name="bookmark_empty">"אין סימניות"</string>
+    <string name="bookmark_exist">"הסימניה כבר קיימת"</string>
+    <string name="bookmark_add_success">"הסימניה נוספה"</string>
+    <string name="bookmark_list">"סימניות"</string>
+    <string name="bookmark_title">"כותרת"</string>
+    <string name="bookmark_location">"מיקום"</string>
+    <string name="delete_all">"מחק הכול"</string>
+    <string name="default_title">"כותרת ברירת מחדל"</string>
+    <string name="more_image">תמונות נוספות</string>
+    <string name="mute_nosupport">לא ניתן להשתיק: וידאו לא נתמך</string>
+    <string name="map_activity_not_found_err">אין יישומי מפות מותקנים להצגת המיקום.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">סרטון אחד</item>
+        <item quantity="two">%1$d סרטונים</item>
+        <item quantity="many">%1$d סרטונים</item>
+        <item quantity="other">%1$d סרטונים</item>
+    </plurals>
+    <string name="cannot_share_items">מספר הפריטים המירבי לשיתוף הוא 300</string>
+    <string name="share_dialogue_title">שתף באמצעות</string>
+    <string name="no_faces">ללא פרצופים</string>
+    <string name="fail_trim">סליחה, קובץ וידאו זה אינו ניתן לחיתוך</string>
+    <string name="can_not_trim">אפשר לחתוך רק קבצי mp4 ו-3gp</string>
+    <string name="drm_license_info">פרטי רישיון DRM</string>
+    <string name="timeline_title">ציר זמן</string>
+    <string name="albums_title">אלבומים</string>
+    <string name="videos_title">סרטונים</string>
+    <string name="action_viewtype_list">תצוגת רשימה</string>
+    <string name="tvEmptyAlbum">לא נמצאו תמונות</string>
+    <string name="tvEmptyVideos">לא נמצאו קבצי וידאו</string>
+    <string name="text_makeup_whiten">מולבן</string>
+    <string name="text_makeup_Soften">מרוכך</string>
+    <string name="text_makeup_trimface">חתוף פנים</string>
+    <string name="text_makeup_bigeye">עניים גדולות</string>
+    <string name="truescanner_normal">רגיל</string>
+    <string name="truescanner_white">לוח ציור</string>
+    <string name="truescanner">סורק אמת</string>
+    <string name="truescanner_remove_glare">הסרת בוהק</string>
+    <string name="hazebuster_acts">מעלים אובך</string>
+    <string name="seestraight_acts">הראה ישר</string>
+    <string name="seestraight_input_image_is_small">התמונה קטנה מדי לעיבוד.</string>
+    <string name="seestraight_process_fail">אי אפשר לעבד את התמונה.</string>
+    <string name="trim_video_exit_title">לבטל שינויים?</string>
+    <string name="trim_video_exit_msg">האם למחוק את השינויים שבוצעו בסרטון?</string>
+    <string name="trim_video_exit_discard">בטל שינויים</string>
+</resources>
diff --git a/res/values-ja/cm_strings.xml b/res/values-ja/cm_strings.xml
new file mode 100644
index 0000000..d8b7d54
--- /dev/null
+++ b/res/values-ja/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">録画時間</string>
+</resources>
diff --git a/res/values-ja/codeaurora_strings.xml b/res/values-ja/codeaurora_strings.xml
new file mode 100644
index 0000000..9911465
--- /dev/null
+++ b/res/values-ja/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">間隔</string>
+    <string name="step_option_desc">早送り/巻き戻しのステップをカスタマイズする</string>
+    <string name="setp_option_three_second">3秒</string>
+    <string name="setp_option_six_second">6秒</string>
+    <string name="loop">"ループ"</string>
+    <string name="single">"シングル"</string>
+    <string name="stereo">"ステレオ"</string>
+    <string name="speaker_on">スピーカーON</string>
+    <string name="speaker_off">スピーカーOFF</string>
+    <string name="speaker_need_headset">この機能を使用するにはヘッドホンを接続してください。</string>
+    <string name="single_track">"シングルトラック"</string>
+    <string name="input_url">"URLを入力"</string>
+    <string name="streaming_settings">"ストリーミングの設定"</string>
+    <string name="next">"次へ"</string>
+    <string name="previous">"前へ"</string>
+    <string name="buffer_size">バッファサイズ</string>
+    <string name="apn">優先APN</string>
+    <string name="rtp_min_port">最小ポート</string>
+    <string name="rtp_max_port">最大ポート</string>
+    <string name="set_rtp_min_port">最小ポートを設定</string>
+    <string name="set_rtp_max_port">最大ポートを設定</string>
+    <string name="set_buffer_size">バッファサイズを設定</string>
+    <string name="set_apn">優先APNを選択</string>
+    <string name="setting">設定</string>
+    <string name="server_timeout_title">"サーバーのタイムアウト"</string>
+    <string name="server_timeout_message">"動画を再生するためにサーバーに再接続しますか?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"接続できませんでした。%1$dに再接続を試みています..."</string>
+    <string name="media_controller_live">ライブ</string>
+    <string name="media_controller_playing">再生中</string>
+    <string name="media_controller_connecting">接続中...</string>
+    <string name="bookmark_add">"ブックマークを追加"</string>
+    <string name="bookmark_display">"ブックマークを表示"</string>
+    <string name="bookmark_empty">"ブックマークがありません"</string>
+    <string name="bookmark_exist">"ブックマークが既に存在しています"</string>
+    <string name="bookmark_add_success">"ブックマークを追加しました"</string>
+    <string name="bookmark_list">"ブックマーク"</string>
+    <string name="bookmark_title">"タイトル"</string>
+    <string name="bookmark_location">"場所"</string>
+    <string name="delete_all">"すべて削除"</string>
+    <string name="default_title">"デフォルトのタイトル"</string>
+    <string name="more_image">他の画像</string>
+    <string name="mute_nosupport">ミュートにできません: 動画がサポートされていません</string>
+    <string name="map_activity_not_found_err">位置情報を表示するマップアプリがインストールされていません。</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d 個の動画</item>
+    </plurals>
+    <string name="cannot_share_items">共有できるアイテム選択数は300までです</string>
+    <string name="share_dialogue_title">共有...</string>
+    <string name="no_faces">顔なし</string>
+    <string name="fail_trim">申し訳ありませんが、このビデオファイルはトリミングできません</string>
+    <string name="can_not_trim">mp4 ファイルおよび 3gp ファイルのみトリミングできます</string>
+    <string name="drm_license_info">DRMライセンス情報</string>
+    <string name="timeline_title">タイムライン</string>
+    <string name="albums_title">アルバム</string>
+    <string name="videos_title">動画</string>
+    <string name="action_viewtype_list">リスト表示</string>
+    <string name="tvEmptyAlbum">写真が見つかりません</string>
+    <string name="tvEmptyVideos">動画が見つかりません</string>
+    <string name="text_makeup_whiten">白くする</string>
+    <string name="text_makeup_Soften">ソフトにする</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+    <string name="truescanner_normal">標準</string>
+    <string name="truescanner_white">ホワイトボード</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">入力された画像が小さすぎます。</string>
+    <string name="seestraight_process_fail">画像を処理できませんでした。</string>
+    <string name="trim_video_exit_title">変更を破棄しますか?</string>
+    <string name="trim_video_exit_msg">この動画に加えられた変更を破棄しますか?</string>
+    <string name="trim_video_exit_discard">破棄</string>
+</resources>
diff --git a/res/values-ka/codeaurora_strings.xml b/res/values-ka/codeaurora_strings.xml
new file mode 100644
index 0000000..247fcd8
--- /dev/null
+++ b/res/values-ka/codeaurora_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="bookmark_location">"მდებარეობა"</string>
+    <string name="default_title">"ნაგულისხმევი სათაური"</string>
+    <string name="map_activity_not_found_err">რუკის არცერთი პროგრამა არაა დაყენებული ამ მდებარეობის საჩვენებლად.</string>
+</resources>
diff --git a/res/values-kn/cm_strings.xml b/res/values-kn/cm_strings.xml
new file mode 100644
index 0000000..97cef74
--- /dev/null
+++ b/res/values-kn/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">ರಿಕಾರ್ಡ್ ಸಮಯ</string>
+</resources>
diff --git a/res/values-kn/codeaurora_strings.xml b/res/values-kn/codeaurora_strings.xml
new file mode 100644
index 0000000..eb55673
--- /dev/null
+++ b/res/values-kn/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ಹಂತ</string>
+    <string name="step_option_desc">ಫಾಸ್ಟ್ ಫಾರ್ವರ್ಡ್/ರಿವೈಂಡ್ ಹಂತವನ್ನು ಕಸ್ಟಮೈಸ್ ಮಾಡಿ</string>
+    <string name="setp_option_three_second">3 ಸೆಕೆಂಡ್‍ಗಳು</string>
+    <string name="setp_option_six_second">6 ಸೆಕೆಂಡ್‍ಗಳು</string>
+    <string name="loop">"ಸುತ್ತುಹಾಕು"</string>
+    <string name="single">"ಏಕ"</string>
+    <string name="stereo">"ಸ್ಟೀರಿಯೋ"</string>
+    <string name="speaker_on">ಧ್ವನಿವರ್ಧಕ ಆನ್</string>
+    <string name="speaker_off">ಧ್ವನಿವರ್ಧಕ ಆಫ್</string>
+    <string name="speaker_need_headset">ಈ ವೈಷಿಷ್ಟ್ಯವನ್ನು ಉಪಯೋಗಿಸಲು ಹೇಡ್‍ಫೋನ್ಸ್ ಪ್ಲಗ್ ಇನ್ ಮಾಡಿ.</string>
+    <string name="single_track">"ಏಕೈಕ ಟ್ರಾಕ್"</string>
+    <string name="input_url">"URL ಬರೆಯಿರಿ"</string>
+    <string name="streaming_settings">"ಸ್ಟ್ರೀಮಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಸ್"</string>
+    <string name="next">"ಮುಂದಿನ"</string>
+    <string name="previous">"ಹಿಂದಿನ"</string>
+    <string name="buffer_size">ಬಫ್ಫರ್ ಗಾತ್ರ</string>
+    <string name="apn">ಆದ್ಯತೆಯ ಎಪಿಎನ್</string>
+    <string name="rtp_min_port">ಕನಿಷ್ಟ ಪೋರ್ಟ್</string>
+    <string name="rtp_max_port">ಗರಿಷ್ಠ ಪೋರ್ಟ್</string>
+    <string name="set_rtp_min_port">ಕನಿಷ್ಠ ಪೋರ್ಟ್ ಹೊಂದಿಸಿ</string>
+    <string name="set_rtp_max_port">ಗರಿಷ್ಠ ಪೋರ್ಟ್ ಹೊಂದಿಸಿ</string>
+    <string name="set_buffer_size">ಬಫ್ಫರ್ ಗಾತ್ರ ಹೊಂದಿಸಿ</string>
+    <string name="set_apn">ಆದ್ಯತೆಯ ಎ‍ಪಿಎನ್ ಆಯ್ಕೆಮಾಡಿ</string>
+    <string name="setting">ಸೆಟ್ಟಿಂಗ್ಸ್</string>
+    <string name="server_timeout_title">"ಸರ್ವರ್ ಅವಧಿಮುಗಿದಿದೆ"</string>
+    <string name="server_timeout_message">"ವೀಡಿಯೋ ಪ್ಲೇಮಾಡಲು ಸರ್ವರ್‍ಗೆ ಮರುಸಂಪರ್ಕಿಸುವುದೇ?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"ಸಂಪರ್ಕ ವಿಫಲವಾಗಿದೆ. %1$d\u2026 ಗೆ ಮರುಸಂಪರ್ಕಿಸಲು ಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="media_controller_live">ಲೈವ್</string>
+    <string name="media_controller_playing">ಪ್ಲೇ ಆಗುತ್ತಿದೆ</string>
+    <string name="media_controller_connecting">ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ\u2026</string>
+    <string name="bookmark_add">"ಬುಕ್‍ಮಾರ್ಕ್ ಸೇರಿಸು"</string>
+    <string name="bookmark_display">"ಬುಕ್‍ಮಾರ್ಕ್ ತೋರಿಸು"</string>
+    <string name="bookmark_empty">"ಯಾವುದೇ ಬುಕ್‍ಮಾರ್ಕ್‍ಗಳಿಲ್ಲ"</string>
+    <string name="bookmark_exist">"ಬುಕ್‍ಮಾರ್ಕ್ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆ"</string>
+    <string name="bookmark_add_success">"ಬುಕ್‍ಮಾರ್ಕ್ ಸೇರಿಸಲಾಗಿದೆ"</string>
+    <string name="bookmark_list">"ಬುಕ್‍ಮಾರ್ಕ್‍ಗಳು"</string>
+    <string name="bookmark_title">"ಶೀರ್ಷಿಕೆ"</string>
+    <string name="bookmark_location">"ಸ್ಥಳ"</string>
+    <string name="delete_all">"ಎಲ್ಲವನ್ನೂ ಅಳಿಸು"</string>
+    <string name="default_title">"ಡೀಫಾಲ್ಟ್ ಶೀರ್ಷಿಕೆ"</string>
+    <string name="more_image">ಮತ್ತಷ್ಟು ಚಿತ್ರಗಳು</string>
+    <string name="mute_nosupport">ಮೌನಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ : ವೀಡಿಯೋ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ</string>
+    <string name="map_activity_not_found_err">ಸ್ಥಳವನ್ನು ಪ್ರದರ್ಶಿಸಲು ಯಾವುದೇ ನಕ್ಷೆ ಆಪ್ ಸ್ಥಾಪಿತವಾಗಿಲ್ಲ.</string>
+    <string name="fail_trim">ಕ್ಷಮಿಸಿ, ಈ ವೀಡಿಯೋ ಕಡತವನ್ನು ಕತ್ತರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ</string>
+    <string name="drm_license_info">DRM ಪರವಾನಗಿ ಮಾಹಿತಿ</string>
+</resources>
diff --git a/res/values-ko/cm_strings.xml b/res/values-ko/cm_strings.xml
new file mode 100644
index 0000000..2946ffc
--- /dev/null
+++ b/res/values-ko/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">녹화 시간</string>
+</resources>
diff --git a/res/values-ko/codeaurora_strings.xml b/res/values-ko/codeaurora_strings.xml
new file mode 100644
index 0000000..2e1d2ad
--- /dev/null
+++ b/res/values-ko/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">간격</string>
+    <string name="step_option_desc">빨리 감기/되감기 간격 사용자 지정</string>
+    <string name="setp_option_three_second">3초</string>
+    <string name="setp_option_six_second">6초</string>
+    <string name="loop">"반복"</string>
+    <string name="single">"단일"</string>
+    <string name="stereo">"스테레오"</string>
+    <string name="speaker_on">스피커 켬</string>
+    <string name="speaker_off">스피커 끔</string>
+    <string name="speaker_need_headset">이 기능을 사용하려면 헤드폰을 연결하세요.</string>
+    <string name="single_track">"단일 트랙"</string>
+    <string name="input_url">"URL 입력"</string>
+    <string name="streaming_settings">"스트리밍 설정"</string>
+    <string name="next">"다음"</string>
+    <string name="previous">"이전"</string>
+    <string name="buffer_size">버퍼 크기</string>
+    <string name="apn">선호 APN</string>
+    <string name="rtp_min_port">최저 포트</string>
+    <string name="rtp_max_port">최고 포트</string>
+    <string name="set_rtp_min_port">최저 포트 설정</string>
+    <string name="set_rtp_max_port">최고 포트 설정</string>
+    <string name="set_buffer_size">버퍼 크기 설정</string>
+    <string name="set_apn">선호 APN 설정</string>
+    <string name="setting">설정</string>
+    <string name="server_timeout_title">"서버 시간 초과"</string>
+    <string name="server_timeout_message">"서버에 다시 접속하여 동영상을 재생할까요?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"연결 실패, %1$d(으)로 다시 연결 중\u2026"</string>
+    <string name="media_controller_live">라이브</string>
+    <string name="media_controller_playing">재생 중</string>
+    <string name="media_controller_connecting">연결 중\u2026</string>
+    <string name="bookmark_add">"즐겨찾기에 추가"</string>
+    <string name="bookmark_display">"즐겨찾기 보기"</string>
+    <string name="bookmark_empty">"즐겨찾기 없음"</string>
+    <string name="bookmark_exist">"즐겨찾기에 이미 존재합니다"</string>
+    <string name="bookmark_add_success">"즐겨찾기에 추가되었습니다"</string>
+    <string name="bookmark_list">"즐겨찾기"</string>
+    <string name="bookmark_title">"제목"</string>
+    <string name="bookmark_location">"위치"</string>
+    <string name="delete_all">"모두 삭제"</string>
+    <string name="default_title">"기본 제목"</string>
+    <string name="more_image">더 많은 이미지</string>
+    <string name="mute_nosupport">음소거할 수 없음: 지원되지 않는 동영상</string>
+    <string name="map_activity_not_found_err">위치를 표시할 지도 앱이 설치되어 있지 않습니다.</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d개 영상</item>
+    </plurals>
+    <string name="cannot_share_items">공유할 수 있는 항목 개수는 최대 300개까지입니다.</string>
+    <string name="share_dialogue_title">공유에 사용할 앱:</string>
+    <string name="no_faces">얼굴 없음</string>
+    <string name="fail_trim">죄송합니다. 이 동영상은 잘라낼 수 없습니다.</string>
+    <string name="can_not_trim">mp4 파일과 3gp 파일만 잘라낼 수 있습니다.</string>
+    <string name="drm_license_info">DRM 라이선스 정보</string>
+    <string name="timeline_title">타임라인</string>
+    <string name="albums_title">앨범</string>
+    <string name="videos_title">영상</string>
+    <string name="action_viewtype_list">목록으로 보기</string>
+    <string name="tvEmptyAlbum">사진이 없습니다.</string>
+    <string name="tvEmptyVideos">영상이 없습니다.</string>
+    <string name="text_makeup_whiten">밝게</string>
+    <string name="text_makeup_Soften">부드럽게</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">눈 키우기</string>
+    <string name="truescanner_normal">기본</string>
+    <string name="truescanner_white">화이트보드</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">빛반사 제거</string>
+    <string name="hazebuster_acts">안개 제거</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">편집하기에는 이미지가 너무 작습니다.</string>
+    <string name="seestraight_process_fail">이미지를 편집할 수 없습니다.</string>
+    <string name="trim_video_exit_title">변경 사항을 취소하시겠습니까?</string>
+    <string name="trim_video_exit_msg">이 영상에 대한 변경 사항을 취소하시겠습니까?</string>
+    <string name="trim_video_exit_discard">변경 사항 취소</string>
+</resources>
diff --git a/res/values-ku/cm_strings.xml b/res/values-ku/cm_strings.xml
new file mode 100644
index 0000000..08b7155
--- /dev/null
+++ b/res/values-ku/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">تۆمارکردنی کات</string>
+</resources>
diff --git a/res/values-ku/codeaurora_strings.xml b/res/values-ku/codeaurora_strings.xml
new file mode 100644
index 0000000..aa11506
--- /dev/null
+++ b/res/values-ku/codeaurora_strings.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">هەنگاو</string>
+    <string name="step_option_desc">بەکەسیکردنی پلەی خێراییی پێشخستن/دواخستن</string>
+    <string name="setp_option_three_second">3 چرکە</string>
+    <string name="setp_option_six_second">6 چرکە</string>
+    <string name="loop">"كلو"</string>
+    <string name="single">"تاک"</string>
+    <string name="stereo">"stereo"</string>
+    <string name="speaker_on">چالاکردنی بڵندگۆ</string>
+    <string name="speaker_off">لەکارخستنی بڵندگۆ</string>
+    <string name="speaker_need_headset">بیستۆکەکان پێوە بکە بۆ بەکارهێنانی ئەم توانستە.</string>
+    <string name="single_track">"تاکە تراک"</string>
+    <string name="input_url">"ناونیشانی ئینتەرنێتی بنووسە"</string>
+    <string name="streaming_settings">"ڕێکخستنەکانی لێشاو (Stream)"</string>
+    <string name="next">"دواتر"</string>
+    <string name="previous">"پێشتر"</string>
+    <string name="buffer_size">قەبارەی نێوانگر</string>
+    <string name="apn">APNی بەباشزانراو</string>
+    <string name="rtp_min_port">کەمترین دەرگا</string>
+    <string name="rtp_max_port">زۆرترین دەرگا</string>
+    <string name="set_rtp_min_port">کەمترین دەرگا دابنێ</string>
+    <string name="set_rtp_max_port">زۆرترین دەرگا دابنێ</string>
+    <string name="set_buffer_size">قەبارەی نێوانگر دابنێ</string>
+    <string name="set_apn">APNی بەباشزانراو دیاری بکە</string>
+    <string name="setting">ڕێکخستنه‌کان</string>
+    <string name="server_timeout_title">"وچانی ڕاژەکار"</string>
+    <string name="server_timeout_message">"ببەستێتەوە بە ڕاژەکارەوە بۆ لێدانی ڤیدیۆکە؟"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"بەستنەوە سەرکەوتوو نەبوو، هەوڵدان بۆ بەستنەوە بە %1$d\u2026"</string>
+    <string name="media_controller_live">ڕاستەوخۆ</string>
+    <string name="media_controller_playing">لێدان</string>
+    <string name="media_controller_connecting">بەستنەوە\u2026</string>
+    <string name="bookmark_add">"نیشانەکردنی وێبگە"</string>
+    <string name="bookmark_display">"پیشاندانی وێبگە نیشانەکراوەکان"</string>
+    <string name="bookmark_empty">"وێبگەی نیشانەکراو نییە"</string>
+    <string name="bookmark_exist">"وێبگەی نیشانەکراو پێشتر هەیە"</string>
+    <string name="bookmark_add_success">"وێبگەکە نیشانە کرا"</string>
+    <string name="bookmark_list">"وێبگە نیشانەکراوەکان"</string>
+    <string name="bookmark_title">"سەردێڕ"</string>
+    <string name="bookmark_location">"شوێن"</string>
+    <string name="delete_all">"سڕینەوەی هەموو"</string>
+    <string name="default_title">"سەردێڕی بنەڕەت"</string>
+    <string name="more_image">وێنەی زیاتر</string>
+    <string name="mute_nosupport">ناتوانێت کپ بکرێت : ڤیدیۆ پشتگیری ناکرێت</string>
+    <string name="map_activity_not_found_err">هیچ بەرنامەیەکی نەخشە نیە بۆ پیشاندانی ناوچە.</string>
+    <string name="fail_trim">بەداخەوە، ئەم پەڕگە ڤیدیۆیییە ناتوانرێت ببڕدرێت</string>
+</resources>
diff --git a/res/values-ku/filtershow_strings.xml b/res/values-ku/filtershow_strings.xml
new file mode 100644
index 0000000..b69ffc0
--- /dev/null
+++ b/res/values-ku/filtershow_strings.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">ده‌ستکاری کردنی وێنه‌</string>
+    <string name="cannot_load_image">ناتوانێت وێنەکە بار بکات!</string>
+    <string name="cannot_edit_original">نه‌توانرا وێنه‌ی بنێڕه‌ت ده‌ستکاریبکرێت</string>
+    <string name="setting_wallpaper">دانانی وێنەی سەر ڕوونما</string>
+    <string name="download_failure">نه‌توانرا وێنه‌ دابگیرێت.هێڵ ئاماده‌نییه‌.</string>
+    <string name="original">ڕەسەن</string>
+    <string name="custom_border">تایبەت بە خۆ</string>
+    <string name="filtershow_undo">پاشگەزبوون</string>
+    <string name="filtershow_redo">گه‌ڕانه‌وه‌ بۆ هه‌نگاوی داهاتوو</string>
+    <string name="show_imagestate_panel">نیشاندانی کاریگه‌رییه‌ جێبه‌جێکراوه‌کان</string>
+    <string name="hide_imagestate_panel">شاردنه‌وه‌ی کاریگه‌رییه‌ جێبه‌جێکراوه‌کان</string>
+    <string name="export_image">ناردن</string>
+    <string name="print_image">چاپکردن</string>
+    <string name="export_flattened">ناردنی وێنه‌ی ته‌خت</string>
+    <string name="select_output_settings">وێنه‌ی نێردراو له‌به‌رده‌گیرێته‌وه‌ به‌بێ تۆمار.</string>
+    <string name="quality">کوالێتی</string>
+    <string name="size">قه‌باره‌</string>
+    <string name="x">x</string>
+    <string name="menu_settings">ڕێکخستنه‌کان</string>
+    <string name="unsaved">چه‌ند گۆڕانێکی پاشه‌که‌وت نه‌کراو هه‌یه‌ بۆ ئه‌م وێنه‌یه‌.</string>
+    <string name="save_before_exit">ئه‌ته‌وێ پاشه‌که‌وتی بکه‌یت پێش چوونه‌ده‌ره‌وه‌؟</string>
+    <string name="save_and_exit">پاشه‌که‌وتکردن و چوونه‌ ده‌ره‌وه‌</string>
+    <string name="save_and_processing">پرۆسه‌ی پڕ کوالێتی وێنه‌...</string>
+    <string name="exit">ده‌رچوون</string>
+    <string name="history">ڕێکخستنەوە</string>
+    <string name="reset">ڕێکخستنەوە</string>
+    <string name="imageState">کاریگه‌ری جێبه‌جێکراو</string>
+    <string name="compare_original">بەراوردکردن</string>
+    <string name="apply_effect">جێبه‌جێکردن</string>
+    <string name="reset_effect">ڕێکخستنەوە</string>
+    <string name="aspect">لا</string>
+    <string name="aspect1to1_effect">1:1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">هیچیان</string>
+    <string name="Fixed">چاره‌سه‌رکراو</string>
+    <string name="tinyplanet">ورده‌ هه‌ساره‌</string>
+    <string name="exposure" msgid="1229093066434614811">ڕووناکیپێدان</string>
+    <string name="sharpness">زبری</string>
+    <string name="contrast">کۆنتراست</string>
+    <string name="vibrance">وزه‌ ڕه‌نگ</string>
+    <string name="saturation">تێرایی</string>
+    <string name="bwfilter">کاریگه‌ری BW</string>
+    <string name="wbalance">خۆکارانه‌ ڕه‌نگ</string>
+    <string name="hue">ڕه‌نگ</string>
+    <string name="shadow_recovery">سێبه‌ره‌کان</string>
+    <string name="highlight_recovery">به‌رچاوه‌کان</string>
+    <string name="curvesRGB">لاری</string>
+    <string name="vignette">تۆخی</string>
+    <string name="vignette_main">شێوە</string>
+    <string name="vignette_exposure">ڕووناکیپێدان</string>
+    <string name="vignette_saturation">تێریی ڕەنگ</string>
+    <string name="vignette_contrast">کۆنتراست</string>
+    <string name="vignette_falloff">که‌وته‌ڕه‌نگ</string>
+    <string name="redeye">چاوی سوور</string>
+    <string name="imageDraw">کێشان</string>
+    <string name="straighten" msgid="5217801513491493491">هێزی</string>
+    <string name="crop" msgid="5584000454518174632">قرتاندن</string>
+    <string name="rotate" msgid="460017689320955494">سووڕاندنەوە</string>
+    <string name="mirror">ئاوێنه‌</string>
+    <string name="negative">پێچه‌وانه‌</string>
+    <string name="none" msgid="3601545724573307541">هیچیان</string>
+    <string name="edge">که‌ناری</string>
+    <string name="kmeans">پاشکه‌وتوو</string>
+    <string name="downsample">خواره‌نمونه‌</string>
+    <string name="grad">وه‌رگیراو</string>
+    <string name="editor_grad_brightness">ڕۆشنایی</string>
+    <string name="editor_grad_contrast">کۆنتراست</string>
+    <string name="editor_grad_saturation">تێریی ڕەنگ</string>
+    <string name="editor_chan_sat_main">سەرەکی</string>
+    <string name="editor_chan_sat_red">سوور</string>
+    <string name="editor_chan_sat_yellow">زەرد</string>
+    <string name="editor_chan_sat_green">سەوز</string>
+    <string name="editor_chan_sat_cyan">شینی ئاسمانی</string>
+    <string name="editor_chan_sat_blue">شین</string>
+    <string name="editor_chan_sat_magenta">سووری ئەرخەوانی</string>
+    <string name="editor_grad_style">شێواز</string>
+    <string name="editor_grad_new">نوێ</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">سوور</string>
+    <string name="curves_channel_green">سه‌وز</string>
+    <string name="curves_channel_blue">شین</string>
+    <string name="draw_style">شێواز</string>
+    <string name="draw_size">قه‌باره‌</string>
+    <string name="draw_hue">ڕه‌نگ</string>
+    <string name="draw_saturation">تێریی ڕەنگ</string>
+    <string name="draw_value">ڕۆشنایی</string>
+    <string name="draw_color">ڕەنگ</string>
+    <string name="draw_style_line">هێله‌کان</string>
+    <string name="draw_style_brush_spatter">دیاریکه‌ره‌کان</string>
+    <string name="draw_style_brush_marker">لیکاوی</string>
+    <string name="draw_clear">پاککردنه‌وه‌</string>
+    <string name="color_border_size">ئه‌ستووری</string>
+    <string name="color_border_corner_size">قه‌باره‌ی سوچه‌کان</string>
+    <string name="color_border_color">ڕەنگ</string>
+    <string name="color_border_clear">پاککردنه‌وه‌</string>
+    <string name="color_pick_select">دیاریکردنی ڕه‌نگی دڵخواز</string>
+    <string name="color_pick_title">دیاریکردنی ڕه‌نگ</string>
+    <string name="draw_size_title">دیاریکردنی قه‌باره‌</string>
+    <string name="draw_size_accept">باشه‌</string>
+    <string name="state_panel_original">ڕەسەن</string>
+    <string name="state_panel_result">ئه‌نجام</string>
+    <string name="filtershow_notification_label">پاشه‌که‌وتکردنی وێنه‌</string>
+    <string name="filtershow_notification_message">پرۆسە...</string>
+    <string name="filtershow_save_preset">پاشه‌که‌وتکردنی ئاماده‌کراوی ئێستا</string>
+    <string name="filtershow_manage_preset">به‌ڕێوه‌بردنی ئاماده‌کراوی به‌کارهێنه‌ر</string>
+    <string name="filtershow_new_preset">ئاماده‌کراوێکی نوێ</string>
+    <string name="filtershow_preset_name">ناوی ئاماده‌کراو</string>
+    <string name="filtershow_show_info_panel">زانیاری</string>
+    <string name="filtershow_show_info_panel_name">ناوی وێنه‌</string>
+    <string name="filtershow_show_info_panel_size">قه‌باره‌ی وێنه‌</string>
+    <string name="filtershow_show_info_panel_histogram">مێژوویی</string>
+    <string name="filtershow_show_info_panel_exif">داتای EXIF </string>
+    <string name="filtershow_add_button_looks">ئاماده‌کراو</string>
+    <string name="filtershow_add_button_versions">وه‌شان</string>
+    <string name="filtershow_version_original">ڕەسەن</string>
+    <string name="filtershow_version_current">ئێستا</string>
+    <string name="filtershow_exif_model">مۆدێل</string>
+    <string name="filtershow_exif_aperture">دیافراگم</string>
+    <string name="filtershow_exif_focal_length">درێژیی تیشکۆیی</string>
+    <string name="filtershow_exif_iso">ISO</string>
+    <string name="filtershow_exif_subject_distance">ماوه‌ی دێڕ</string>
+    <string name="filtershow_exif_date">ڕۆژی گرتنی وێنه‌که‌</string>
+    <string name="filtershow_exif_f_stop">F وه‌ستان</string>
+    <string name="filtershow_exif_exposure_time">كاتى كەوتنەبەر</string>
+    <string name="filtershow_exif_copyright">مافی له‌به‌رگرتنه‌وه‌</string>
+</resources>
diff --git a/res/values-ku/strings.xml b/res/values-ku/strings.xml
new file mode 100644
index 0000000..1455c3d
--- /dev/null
+++ b/res/values-ku/strings.xml
@@ -0,0 +1,431 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">پێشەنگا</string>
+    <string name="gadget_title">چوارچێوه‌ی وێنه‌</string>
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="movie_view_label">لێده‌ری ڤیدیۆ</string>
+    <string name="loading_video">بارکردنی ڤیدیۆ\u2026</string>
+    <string name="loading_image">کردنه‌وه‌ی وێنه‌\u2026</string>
+    <string name="loading_account">کردنه‌وه‌ی هه‌ژمار\u2026</string>
+    <string name="resume_playing_title">ڤيديۆكه‌ دەست پێ بكەوە</string>
+    <string name="resume_playing_message">ڤیدیۆ ده‌ستپێبکاته‌وه‌ له‌ %s ؟ ?</string>
+    <string name="resume_playing_resume">ده‌ستپێکردنه‌وه‌</string>
+    <string name="loading">ئامادەکردن\u2026</string>
+    <string name="fail_to_load">نەتوانى بار بكه‌یت</string>
+    <string name="fail_to_load_image">ناتوانی وێنه‌كه‌ باربكه‌یت</string>
+    <string name="no_thumbnail">هیچ کورته‌ وێنه‌یه‌ک نییه‌</string>
+    <string name="resume_playing_restart">دەست پێ بكەوە</string>
+    <string name="crop_save_text">باشه‌</string>
+    <string name="ok">باشه‌</string>
+    <string name="multiface_crop_help">په‌نجه‌ بنێ به‌ ڕوودا بۆ ده‌ستپێکردن.</string>
+    <string name="saving_image">پاشه‌که‌وتکردنی وێنه‌\u2026</string>
+    <string name="filtershow_saving_image">پاشه‌که‌وتکردنی وێنه‌ بۆ <xliff:g id="album_name">%1$s</xliff:g>\u2026</string>
+    <string name="save_error">نه‌توانرا وێنه‌ی بڕدراو پاشه‌که‌وت بکرێت.</string>
+    <string name="crop_label">بڕینی وێنه‌</string>
+    <string name="trim_label">بڕینی ڤیدیۆ</string>
+    <string name="select_image">دیاریکردنی وێنه‌</string>
+    <string name="select_video">دیاریکردنی ڤیدیۆ</string>
+    <string name="select_item">دیاریکردنی دانه‌یه‌ک</string>
+    <string name="select_album">دیاریکردنی ئه‌لبوم</string>
+    <string name="select_group">دیاریکردنی گروپ</string>
+    <string name="set_image">دانانی وێنە وەکوو</string>
+    <string name="set_wallpaper">دانانی وێنەی پشتەوە</string>
+    <string name="wallpaper">دانانی دیوارپۆش\u2026</string>
+    <string name="camera_setas_wallpaper">دیوارپۆش</string>
+    <string name="delete">سڕینه‌وه‌</string>
+    <plurals name="delete_selection">
+        <item quantity="one">سڕینەوەی بڕگه‌ی دیاریکراو؟</item>
+        <item quantity="other">سڕینەوەی بڕگه‌ دیاریکراوەکان؟</item>
+    </plurals>
+    <string name="confirm">دووپاتکردنەوە</string>
+    <string name="cancel">لابردن</string>
+    <string name="share">به‌شداری پێکردن</string>
+    <string name="share_panorama">هاوبەشیکردنی پانۆراما</string>
+    <string name="share_as_photo">هاوبەشیکردن وەکوو وێنە</string>
+    <string name="deleted">سڕایەوە</string>
+    <string name="undo">پاشگەزبوونەوە</string>
+    <string name="select_all">دیاریکردنی هەموو</string>
+    <string name="deselect_all">دیاری نەکردنی هەموو</string>
+    <string name="slideshow">نیشاندانی سلاید</string>
+    <string name="details">زانیاری زیاتر</string>
+    <string name="details_title">%1$d له‌ %2$d دانه‌:</string>
+    <string name="close">داخستن</string>
+    <string name="switch_to_camera">گۆڕین بۆ كامێرا</string>
+    <plurals name="number_of_items_selected">
+        <item quantity="one">%1$d دیاریکرا</item>
+        <item quantity="other">%1$d دیاریکراون</item>
+    </plurals>
+    <plurals name="number_of_albums_selected">
+        <item quantity="one">%1$d دیاریکرا</item>
+        <item quantity="other">%1$d دیاریکراون</item>
+    </plurals>
+    <plurals name="number_of_groups_selected">
+        <item quantity="one">%1$d دیاریکرا</item>
+        <item quantity="other">%1$d دیاریکراون</item>
+    </plurals>
+    <string name="show_on_map">پیشاندانی لەسەر نەخشە</string>
+    <string name="rotate_left">سووڕاندنەوە بۆ چەپ</string>
+    <string name="rotate_right">سووڕاندنەوە بۆ ڕاست</string>
+    <string name="no_such_item">نه‌توانرا دانه‌ بدۆزرێته‌وه‌.</string>
+    <string name="edit">دەستکاری</string>
+    <string name="simple_edit">ده‌ستكاری كرنی سادە</string>
+    <string name="process_caching_requests">دەستكاريكردنی داواكارى هەڵگرتن</string>
+    <string name="caching_label">هەڵگرتن\u2026</string>
+    <string name="crop_action">قرتاندن</string>
+    <string name="trim_action">بڕین</string>
+    <string name="mute_action">کپکردن</string>
+    <string name="set_as">دانان وەکوو</string>
+    <string name="video_mute_err">ناتوانیت ڤیدیۆكه‌ بێده‌نگ بكه‌یت</string>
+    <string name="video_err">ناتوانرێت ڤیدۆکە لێبدرێت.</string>
+    <string name="group_by_location">له‌لایه‌ن شوێنه‌وه‌</string>
+    <string name="group_by_time">له‌لایه‌ن كاته‌وه‌</string>
+    <string name="group_by_tags">له‌لایه‌ن تاگه‌كانه‌وه‌</string>
+    <string name="group_by_faces">له‌لایه‌ن خه‌ڵكه‌وه‌</string>
+    <string name="group_by_album">له‌لایه‌ن ئه‌لبومه‌وه‌</string>
+    <string name="group_by_size">به‌پێی قه‌باره‌</string>
+    <string name="untagged">ئاراسته‌بۆنه‌کراو</string>
+    <string name="no_location">شوێن نییه‌</string>
+    <string name="no_connectivity">هه‌ندێ شوێن نه‌توانرا بناسرێته‌وه‌ له‌ کاتی کێشه‌کانی هێڵ.</string>
+    <string name="sync_album_error">نه‌توانرا وێنه‌ دابگیرێت بۆ ئه‌لبوومه‌که‌. دواتر هه‌وڵبده‌ره‌وه‌.</string>
+    <string name="show_images_only">ته‌نها وێنه‌</string>
+    <string name="show_videos_only">ته‌نها ڤیدیۆ</string>
+    <string name="show_all">وێنه‌ وamp; ڤیدیۆ</string>
+    <string name="appwidget_title">پێشەنگای وێنە</string>
+    <string name="appwidget_empty_text">وێنه‌ نییه‌.</string>
+    <string name="crop_saved">        وێنەی قرتێنراو پاشەکەوت کرا بۆ <xliff:g id="folder_name">%s</xliff:g>.</string>
+    <string name="no_albums_alert">هیچ ئه‌لبومێک ئاماده‌ نییه‌.</string>
+    <string name="empty_album">0 وێنه‌/ڤیدیۆ ئاماده‌یه‌.</string>
+    <string name="picasa_posts">په‌یامه‌کان</string>
+    <string name="make_available_offline">کردن بە دەرهێڵ</string>
+    <string name="sync_picasa_albums">تازەکردنەوە</string>
+    <string name="done">ئه‌نجام درا</string>
+    <string name="sequence_in_set">%1$d of %2$d items:</string>
+    <string name="title">سەردێڕ</string>
+    <string name="description">پێناسه</string>
+    <string name="time">کات</string>
+    <string name="location">شوێن</string>
+    <string name="path">ڕێچکە</string>
+    <string name="width">پانی</string>
+    <string name="height">بەرزی</string>
+    <string name="orientation">ڕووتێکەری</string>
+    <string name="duration">ماوه‌</string>
+    <string name="mimetype">جۆری MIME</string>
+    <string name="file_size">ئەندازە پەڕگە</string>
+    <string name="maker">دروستکەر</string>
+    <string name="model">مۆدێل</string>
+    <string name="flash">فلاش</string>
+    <string name="aperture">دیافراگم</string>
+    <string name="focal_length">درێژیی تیشکۆیی</string>
+    <string name="white_balance">هاوسەنگیی سپی</string>
+    <string name="exposure_time">کاتی ڕووناککردنەوە</string>
+    <string name="iso">ISO</string>
+    <string name="unit_mm">م‌م</string>
+    <string name="manual">دەستکارانە</string>
+    <string name="auto">خۆکارانه</string>
+    <string name="flash_on">فلاش لێدرا</string>
+    <string name="flash_off">بێ فلاش</string>
+    <string name="unknown">نەزانراو</string>
+    <string name="ffx_original">ڕەسەن</string>
+    <string name="ffx_vintage">بەپەرۆش</string>
+    <string name="ffx_instant">دەستبەجێ</string>
+    <string name="ffx_bleach">سپی دەکاتەوە</string>
+    <string name="ffx_blue_crush">شین</string>
+    <string name="ffx_bw_contrast">B/W</string>
+    <string name="ffx_punch">كۆن كردنی كاغه‌ز</string>
+    <string name="ffx_x_process">كرداری X</string>
+    <string name="ffx_washout">ژاوەژاو</string>
+    <string name="ffx_washout_color">Litho</string>
+    <plurals name="make_albums_available_offline">
+        <item quantity="one">دروستکردنی ئه‌لبومی ده‌رهێڵی</item>
+        <item quantity="other">دروستکردنی ئه‌لبومی ده‌رهێڵی</item>
+    </plurals>
+    <string name="try_to_set_local_album_available_offline">        ئەم بڕگەیە له‌ ناوخۆدا پاشەکەوتکراوە و به‌بێ هێڵیش به‌رده‌سته‌.</string>
+    <string name="set_label_all_albums">هه‌موو ئه‌لبومه‌كانم</string>
+    <string name="set_label_local_albums">شوێنی ئه‌لبومه‌كان</string>
+    <string name="set_label_mtp_devices">ئامێری MTP</string>
+    <string name="set_label_picasa_albums">Picasa albums</string>
+    <string name="free_space_format"><xliff:g id="bytes">%s</xliff:g> free</string>
+    <string name="size_below"><xliff:g id="size">%1$s</xliff:g> or below</string>
+    <string name="size_above"><xliff:g id="size">%1$s</xliff:g> or above</string>
+    <string name="size_between"><xliff:g id="min_size">%1$s</xliff:g> to <xliff:g id="max_size">%2$s</xliff:g></string>
+    <string name="Import">هێنان</string>
+    <string name="import_complete">به‌سه‌ركه‌وتوی هێندرا</string>
+    <string name="import_fail">هێنان سه‌ركه‌وتوو نه‌بوو</string>
+    <string name="camera_connected">كامێرای پەیوەندیدار</string>
+    <string name="camera_disconnected">كامێرای په‌یوه‌ندیدار.</string>
+    <string name="click_import">دەست لێدان لێرە بۆ هێنان</string>
+    <string name="widget_type_album">ئه‌لبومێك هه‌ڵبژێره‌</string>
+    <string name="widget_type_shuffle">تێکەڵکردنی هه‌موو وێنه‌كان</string>
+    <string name="widget_type_photo">وێنه‌یه‌ك هه‌ڵبژێره‌</string>
+    <string name="widget_type">هەڵبژاردنی وێنه‌</string>
+    <string name="slideshow_dream_name">نیشانده‌ری</string>
+    <string name="albums">ئەلبوم</string>
+    <string name="times">کەڕەت</string>
+    <string name="locations">شوێن</string>
+    <string name="people">خەڵک</string>
+    <string name="tags">تاگەکان</string>
+    <string name="group_by">له‌لایه‌ن گروپه‌وه‌</string>
+    <string name="settings">ڕێکخستنه‌کان</string>
+    <string name="add_account">دانانی هەژمار</string>
+    <string name="folder_camera">کامێرا</string>
+    <string name="folder_download">داگرتن</string>
+    <string name="folder_edited_online_photos">وێنه‌ی سه‌رهێڵ دەستکاری کراوە</string>
+    <string name="folder_imported">دانان</string>
+    <string name="folder_screenshot">وێنەی شاشە</string>
+    <string name="help">یارمەتی</string>
+    <string name="no_external_storage_title">هیچ هه‌ڵنه‌گیراوه‌</string>
+    <string name="no_external_storage">هیچ هه‌ڵگیراوێكی ده‌ره‌كی نییه‌</string>
+    <string name="switch_photo_filmstrip">پیشاندانی بە شێوەی ئەڵقەی فیلم</string>
+    <string name="switch_photo_grid">پیشاندانی خانه‌یی</string>
+    <string name="switch_photo_fullscreen">بینینی پڕ شاشە</string>
+    <string name="trimming">زیانبەخش</string>
+    <string name="muting">بێ دەنگ</string>
+    <string name="please_wait">تکایه‌ چاوه‌ڕێ بکە</string>
+    <string name="save_into">Saving video to <xliff:g id="album_name">%1$s</xliff:g> \u2026</string>
+    <string name="trim_too_short">ناتوانیت هه‌ڵی بگریت:ڤیدیۆی دیاری كراو زۆر كورته‌</string>
+    <string name="pano_progress_text">نواندنی پانۆرامایی</string>
+    <string name="save" msgid="8140440041190264400">پاشەکەوتکردن</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">پشكنینی ناوه‌ڕۆك...</string>
+    <plurals name="ingest_number_of_items_scanned">
+        <item quantity="one">%1$d بڕگە پشکنرا</item>
+        <item quantity="other">%1$d بڕگە پشکنرا</item>
+    </plurals>
+    <string name="ingest_sorting" msgid="624687230903648118">جیاكردنه‌وه‌...</string>
+    <string name="ingest_scanning_done">پشكنین ته‌واو بوو</string>
+    <string name="ingest_importing">دانان...</string>
+    <string name="ingest_empty_device">هيچ ناوەرۆكى بەردەست بۆ دانان لەسەر ئەمە ئامراز نيە.</string>
+    <string name="ingest_no_device">هیچ ئامێرێكی MTP په‌یوه‌ست نییه‌</string>
+    <string name="camera_error_title">هەڵەی کامێرا</string>
+    <string name="cannot_connect_camera">ناتوانێت ببەسترێتەوە بە کامێراوە.</string>
+    <string name="camera_disabled">کامێرا بە هۆکاری پلانی پاراستنەوە  نەتوانا کراوە.</string>
+    <string name="camera_label">کامێرا</string>
+    <string name="wait">تکایە چاوەڕێ بکە\u2026</string>
+    <string name="no_storage" product="nosdcard">ده‌رکردنی بیرگه‌ی USB پێش به‌کارهێنانی کامێرا.</string>
+    <string name="no_storage" product="default">پێش بەکارهێنانی کامێرا بیرگەی دەرەکی تێبخە.</string>
+    <string name="preparing_sd" product="nosdcard">ئاماده‌کردنی بیرگه‌ی USB\u2026</string>
+    <string name="preparing_sd" product="default">ئامادەکردنی بیرگەی دەرەکی\u2026</string>
+    <string name="access_sd_fail" product="nosdcard">ده‌سته‌ڵات نه‌شكێنرایه‌وه‌ به‌سه‌ر بیرگه‌ی USB.</string>
+    <string name="access_sd_fail" product="default">نەتوانرا دەست بگەیەنێتە بیرگەی دەرەکی.</string>
+    <string name="review_cancel">لابردن</string>
+    <string name="review_ok">ته‌واوبوو</string>
+    <string name="time_lapse_title">تۆمارکردنی تێپەڕبوونی کات</string>
+    <string name="pref_camera_id_title">کامێرا هەڵبژێرە</string>
+    <string name="pref_camera_id_entry_back">دواوە</string>
+    <string name="pref_camera_id_entry_front">پێشەوە</string>
+    <string name="pref_camera_recordlocation_title">کۆگاکردنی شوێن</string>
+    <string name="pref_camera_location_label">شوێن</string>
+    <string name="pref_camera_timer_title">کاتژمێری بەرەوژێرژمار</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="one">١ چرکە</item>
+        <item quantity="other">%d چرکە</item>
+    </plurals>
+    <string name="pref_camera_timer_sound_default">@string/setting_on_value</string>
+    <string name="pref_camera_timer_sound_title">توتە لە ماوەی ژماردنی بەرەوژێر</string>
+    <string name="setting_off">کوژاندن</string>
+    <string name="setting_on">هەڵکردن</string>
+    <string name="pref_video_quality_title">جۆرایه‌تیی کامێرا</string>
+    <string name="pref_video_quality_entry_high">به‌رز</string>
+    <string name="pref_video_quality_entry_low">نزم</string>
+    <string name="pref_video_time_lapse_frame_interval_title">کات تێپەڕبوون</string>
+    <string name="pref_camera_settings_category">ڕێکخستنەکانی کامێرا</string>
+    <string name="pref_camcorder_settings_category">ڕێکخستنەکانی کامێرای هەڵگرتەنی</string>
+    <string name="pref_camera_picturesize_title">قەبارەی وێنە</string>
+    <string name="pref_camera_picturesize_entry_13mp">١٣ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_8mp">٨ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_5mp">٥ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_4mp">4 مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_3mp">٣ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_2mp">٢ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">٢ مێگاپێکسڵ (١٦ لەسەر ٩)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">١.٣ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_1mp">١ مێگاپێکسڵ</string>
+    <string name="pref_camera_picturesize_entry_vga">VGA</string>
+    <string name="pref_camera_picturesize_entry_qvga">QVGA</string>
+    <string name="pref_camera_focusmode_title">شێوازی سەرنجدان</string>
+    <string name="pref_camera_focusmode_entry_auto">خۆکار</string>
+    <string name="pref_camera_focusmode_entry_infinity">Infinity</string>
+    <string name="pref_camera_focusmode_entry_macro">Macro</string>
+    <string name="pref_camera_focusmode_label_auto">خۆکارانە</string>
+    <string name="pref_camera_focusmode_label_infinity">INFINITY</string>
+    <string name="pref_camera_focusmode_label_macro">MACRO</string>
+    <string name="pref_camera_flashmode_title">شێوازی فلاش</string>
+    <string name="pref_camera_flashmode_label">شێوازی فلاش</string>
+    <string name="pref_camera_flashmode_entry_auto">خۆکارانه‌</string>
+    <string name="pref_camera_flashmode_entry_on">هەڵکردن</string>
+    <string name="pref_camera_flashmode_entry_off">کوژاندنه‌وه‌</string>
+    <string name="pref_camera_flashmode_label_auto">فلاشی خۆکار</string>
+    <string name="pref_camera_flashmode_label_on">فلاش هەڵە</string>
+    <string name="pref_camera_flashmode_label_off">فلاش کوژاوەیە</string>
+    <string name="pref_camera_whitebalance_title">هاوسەنگیی سپی</string>
+    <string name="pref_camera_whitebalance_label">هاوسه‌نگیی سپێتی</string>
+    <string name="pref_camera_whitebalance_entry_auto">خۆکار</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">درەوشاوە</string>
+    <string name="pref_camera_whitebalance_entry_daylight">ڕۆژی ڕووناک</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">تيشكاوى</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">هەوری</string>
+    <string name="pref_camera_whitebalance_label_auto">خۆکار</string>
+    <string name="pref_camera_whitebalance_label_incandescent">درەوشاوە</string>
+    <string name="pref_camera_whitebalance_label_daylight">ڕۆژی ڕووناک</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">تيشكاوى</string>
+    <string name="pref_camera_whitebalance_label_cloudy">هەوری</string>
+    <string name="pref_camera_scenemode_title">شێوازی دیمەن</string>
+    <string name="pref_camera_scenemode_entry_auto">خۆکار</string>
+    <string name="pref_camera_scenemode_entry_hdr">HDR</string>
+    <string name="pref_camera_scenemode_entry_action">چالاکی</string>
+    <string name="pref_camera_scenemode_entry_night">شەو</string>
+    <string name="pref_camera_scenemode_entry_sunset">خۆراوابوون</string>
+    <string name="pref_camera_scenemode_entry_party">میوانی</string>
+    <string name="pref_camera_scenemode_label_auto">هیچیان</string>
+    <string name="pref_camera_scenemode_label_action">چالاکی</string>
+    <string name="pref_camera_scenemode_label_night">شەو</string>
+    <string name="pref_camera_scenemode_label_sunset">خۆراوابوون</string>
+    <string name="pref_camera_scenemode_label_party">میوانی</string>
+    <string name="pref_camera_countdown_label">ژمێره‌ری کات</string>
+    <string name="pref_camera_countdown_label_off">کوژاندنەوەی کاتڕاگر</string>
+    <string name="pref_camera_countdown_label_one">١ چرکە</string>
+    <string name="pref_camera_countdown_label_three">٣ چرکە</string>
+    <string name="pref_camera_countdown_label_ten">١٠ چرکە</string>
+    <string name="pref_camera_countdown_label_fifteen">١٥ چرکە</string>
+    <string name="not_selectable_in_scene_mode">لە شیوازی دیمەندا دیارینەکراوەیە.</string>
+    <string name="pref_exposure_title">ڕووناکیپێدان</string>
+    <string name="pref_exposure_label">ڕۆشنایی پێدان</string>
+    <string name="pref_camera_hdr_default">@string/setting_off_value</string>
+    <string name="pref_camera_hdr_label">HDR</string>
+    <string name="pref_camera_id_label_back">کامێرای پێشەوە</string>
+    <string name="pref_camera_id_label_front">کامێرای دواوە</string>
+    <string name="dialog_ok">باشه‌</string>
+    <string name="spaceIsLow_content" product="nosdcard">بیرگەکەت پڕ بوە تکایە لەپێشدا کەمێك زانیاری بسڕەوە و پاشان هەوڵ بدەرەوە.</string>
+    <string name="spaceIsLow_content" product="default">بۆشاییی بیرگەی دەرەکیت بەرەو تەواوبوون دەڕوات. ڕێکخستنەکانی جۆرێتی بگۆڕە یان هەندێک وێنە یان دیکەی پەڕگەکان بسڕەوە.</string>
+    <string name="video_reach_size_limit">قەبارە گەیشتۆتە سنوور.</string>
+    <string name="pano_too_fast_prompt">زۆر خێرا</string>
+    <string name="pano_dialog_prepare_preview">ئامادەکردنی پانۆراما</string>
+    <string name="pano_dialog_panorama_failed">نەیتوانی پانۆراما پاشەکەوت بکات.</string>
+    <string name="pano_dialog_title">پانۆراما</string>
+    <string name="pano_capture_indication">گرتنی پانۆراما</string>
+    <string name="pano_dialog_waiting_previous">چاوەڕێکردن بۆ پانۆرامای پێشوو</string>
+    <string name="pano_review_saving_indication_str">پاشەکەوتکردن\u2026</string>
+    <string name="pano_review_rendering">نواندنی پانۆرامایی</string>
+    <string name="tap_to_focus">بیسوو بۆ سەرنجدان.</string>
+    <string name="pref_video_effect_title">کاریگه‌رییه‌کان</string>
+    <string name="effect_none">هیچیان</string>
+    <string name="effect_goofy_face_squeeze">گوشین</string>
+    <string name="effect_goofy_face_big_eyes">چاوی گەورە</string>
+    <string name="effect_goofy_face_big_mouth">دەمی گەورە</string>
+    <string name="effect_goofy_face_small_mouth">دەمی بچوک</string>
+    <string name="effect_goofy_face_big_nose">لوتی گەورە</string>
+    <string name="effect_goofy_face_small_eyes">چاوی بچوک</string>
+    <string name="effect_backdropper_space">لە بۆشایی</string>
+    <string name="effect_backdropper_sunset">خۆراوابوون</string>
+    <string name="effect_backdropper_gallery">ڤیدیۆکه‌ت</string>
+    <string name="bg_replacement_message">دانانی ئامێر بۆ وه‌ستان.\nهه‌نگاوێک له‌ بینینی کات.</string>
+    <string name="video_snapshot_hint">له‌ کاتی تۆمارکردندا بیسوو بۆ وێنه‌گرتن.</string>
+    <string name="video_recording_started">تۆمارکردنی ڤیدیۆ دەستی پێکردووه‌.</string>
+    <string name="video_recording_stopped">تۆمارکردنی ڤیدیۆ وەستاوه‌.</string>
+    <string name="disable_video_snapshot_hint">گرتنی ڤیدیۆ ئاماده‌نییه‌ کاتێک کاریگه‌ری تایبه‌تی کارده‌کات.</string>
+    <string name="clear_effects">پاککردنەوەی کاریگەرییەکان</string>
+    <string name="effect_silly_faces">ڕووخساری گەمژانه‌</string>
+    <string name="effect_background">پاشبنەما</string>
+    <string name="accessibility_shutter_button">دوگمه‌ی خێرایی لێنس</string>
+    <string name="accessibility_menu_button">دوگمەی پێڕست</string>
+    <string name="accessibility_review_thumbnail">تازه‌ترین وێنه‌</string>
+    <string name="accessibility_camera_picker">گۆڕینی پێش و دواوه‌ی کامێرا</string>
+    <string name="accessibility_mode_picker">کامێرا، ڤیدیۆ یان هەڵبژێرەری پانۆراما</string>
+    <string name="accessibility_second_level_indicators">ڕێکخستنی زیاتری سه‌رپه‌رشتی</string>
+    <string name="accessibility_back_to_first_level">داخستنی ڕێکخستنی سه‌رپه‌رشتی</string>
+    <string name="accessibility_zoom_control">سه‌رپه‌رشتی هێنانه‌ پێشه‌وه‌</string>
+    <string name="accessibility_decrement">که‌مکردن%1$s</string>
+    <string name="accessibility_increment">زیادکردن%1$s</string>
+    <string name="accessibility_check_box">%1$s خانه‌ی پیاچوونه‌وه‌</string>
+    <string name="accessibility_switch_to_camera">گۆڕان بۆ وێنە</string>
+    <string name="accessibility_switch_to_video">گۆڕان بۆ ڤیدیۆ</string>
+    <string name="accessibility_switch_to_panorama">گۆڕان بۆ پانۆراما</string>
+    <string name="accessibility_switch_to_new_panorama">گۆڕین بوێ پانۆرامای نوێ</string>
+    <string name="accessibility_switch_to_refocus">گۆڕین بۆ دووباره‌ فۆکس</string>
+    <string name="accessibility_review_cancel">چاوپێداگێڕانەوەی هەڵوەشاندنەوە</string>
+    <string name="accessibility_review_ok">چاوپێداگێڕانەوە کرا</string>
+    <string name="accessibility_review_retake">چاوپێداگێڕانەوەی وێنەگرتنەوە</string>
+    <string name="accessibility_play_video">لێدانی ڤیدیۆ</string>
+    <string name="accessibility_pause_video">ڕاگرتنی ڤیدیۆ</string>
+    <string name="accessibility_reload_video">دووباره‌کردنه‌وه‌ی ڤیدیۆ</string>
+    <string name="accessibility_time_bar">شریتی کاتی لێده‌ری ڤیدیۆ</string>
+    <string name="capital_on">هەڵکردن</string>
+    <string name="capital_off">کوژاندن</string>
+    <string name="pref_video_time_lapse_frame_interval_off">کوژاندن</string>
+    <string name="pref_video_time_lapse_frame_interval_500">٠.٥ چرکه‌</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">١ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">١.٥ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">٢ چرکه‌</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">٢.٥  چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">٣ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">٤ چرکه‌</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">٥ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">٦ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">١٠ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">١٢ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">١٥ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">٢٤ چرکە</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">٠.٥ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">١ خوله‌ک</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">١.٥ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">٢ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">٢.٥ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">٣ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">٤ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">٥ خوله‌ک</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">٦ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">١٠ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">١٢ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">١٥ خوله‌ک</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">٢٤ خولەک</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">٠.٥ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">١ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">١.٥ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">٢ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">٢.٥ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">٣ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">٤ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">٥ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">٦ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">١٠ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">١٢ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">١٥ کاژێر</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">٢٤ کاژێر</string>
+    <string name="time_lapse_seconds">چرکە</string>
+    <string name="time_lapse_minutes">خولەک</string>
+    <string name="time_lapse_hours">کاژێر</string>
+    <string name="time_lapse_interval_set">کرا</string>
+    <string name="set_time_interval">دانانی مەودای کات</string>
+    <string name="set_time_interval_help">تایبەتمەندیی تێپەڕینی کات کوژاوەیە. هەڵی بکە بۆ دانانی مەودای کات.</string>
+    <string name="set_timer_help">کات پێوه‌ر کوژاوه‌ته‌وه‌.دایبگیرسێنه‌ ئه‌گه‌ر بۆ ژماردنته‌ پێش گرتنی وێنه‌.</string>
+    <string name="set_duration">دانانی ماوە لە چەند چرکەدا</string>
+    <string name="count_down_title_text">ژماردنی بەرەوژێر تاوەکوو گرتنی وێنە</string>
+    <string name="remember_location_title">شوێنی وێنه‌کانت له‌ یاده‌؟</string>
+    <string name="remember_location_prompt">وێنە و ڤيديۆکانت به شوێنی گرتنه‌کانیانه‌وه‌ پینە بکە. \n\nبەرنامەکانی تر دەتوانن دەست پێ راگەیەنن به‌م زانیارییه‌وه‌ کە له‌گه‌ڵ وێنه‌ پاشه‌که‌وتکراوه‌کانتدایە.</string>
+    <string name="remember_location_no">نا سپاس</string>
+    <string name="remember_location_yes">بەڵێ</string>
+    <string name="menu_camera">کامێرا</string>
+    <string name="menu_search">گه‌ڕان</string>
+    <string name="tab_photos">وێنه‌کان</string>
+    <string name="tab_albums">ئەلبوم</string>
+    <string name="camera_menu_more_label">بەربژاردەی زیاتر</string>
+    <string name="camera_menu_settings_label">ڕێکخستنەکان</string>
+    <plurals name="number_of_photos">
+        <item quantity="one">%1$d وێنه‌</item>
+        <item quantity="other">%1$d وێنه‌</item>
+    </plurals>
+</resources>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 6ca7e91..cee058d 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -35,7 +35,7 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_centerVertical">true</item>
-        <item name="android:layout_marginRight">@dimen/setting_popup_right_margin</item>
+        <item name="android:layout_marginEnd">@dimen/setting_popup_right_margin</item>
         <item name="android:visibility">gone</item>
     </style>
     <style name="PopupTitleText">
@@ -45,19 +45,19 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">@color/popup_title_color</item>
-        <item name="android:layout_marginLeft">10dp</item>
-        <item name="android:paddingLeft">16dp</item>
+        <item name="android:layout_marginStart">10dp</item>
+        <item name="android:paddingStart">16dp</item>
     </style>
     <style name="ViewfinderLabelLayout">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
-        <item name="android:layout_marginLeft">13dp</item>
-        <item name="android:layout_marginRight">@dimen/indicator_bar_width</item>
+        <item name="android:layout_marginStart">13dp</item>
+        <item name="android:layout_marginEnd">@dimen/indicator_bar_width</item>
         <item name="android:layout_marginBottom">13dp</item>
         <item name="android:layout_marginTop">13dp</item>
     </style>
         <style name="PanoViewHorizontalBar">
-        <item name="android:background">#000000</item>
+        <item name="android:background">@color/black</item>
         <item name="android:alpha">1.0</item>
         <item name="android:layout_height">0dp</item>
         <item name="android:layout_width">match_parent</item>
@@ -67,8 +67,8 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:layout_centerVertical">true</item>
-        <item name="android:layout_alignParentRight">true</item>
-        <item name="android:layout_marginRight">@dimen/setting_popup_right_margin</item>
+        <item name="android:layout_alignParentEnd">true</item>
+        <item name="android:layout_marginEnd">@dimen/setting_popup_right_margin</item>
         <item name="android:visibility">gone</item>
     </style>
 
diff --git a/res/values-lb/cm_strings.xml b/res/values-lb/cm_strings.xml
new file mode 100644
index 0000000..f159db5
--- /dev/null
+++ b/res/values-lb/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Opnamezäit</string>
+</resources>
diff --git a/res/values-lb/codeaurora_strings.xml b/res/values-lb/codeaurora_strings.xml
new file mode 100644
index 0000000..68e2b2b
--- /dev/null
+++ b/res/values-lb/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Schrëtt</string>
+    <string name="step_option_desc">Vir- an Zréckspull-Schrëtter upassen</string>
+    <string name="setp_option_three_second">3 Sekonnen</string>
+    <string name="setp_option_six_second">6 Sekonnen</string>
+    <string name="loop">"Widderhuelen"</string>
+    <string name="single">"Eenzel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Lautsprecher UN</string>
+    <string name="speaker_off">Lautsprecher AUS</string>
+    <string name="speaker_need_headset">Schléis Kopfhörer u fir dës Funktioun ze benotzen.</string>
+    <string name="single_track">"Eenzel Spur"</string>
+    <string name="input_url">"URL aginn"</string>
+    <string name="streaming_settings">"Streamingastellungen"</string>
+    <string name="next">"Weider"</string>
+    <string name="previous">"Zréck"</string>
+    <string name="buffer_size">Tëschespäicher-Gréisst</string>
+    <string name="apn">Preferéierten APN</string>
+    <string name="rtp_min_port">Min. Port</string>
+    <string name="rtp_max_port">Max. Port</string>
+    <string name="set_rtp_min_port">Min. Port festleeën</string>
+    <string name="set_rtp_max_port">Max. Port festleeën</string>
+    <string name="set_buffer_size">Tëschespäichergréisst definéieren</string>
+    <string name="set_apn">Preferéierten APN auswielen</string>
+    <string name="setting">Astellungen</string>
+    <string name="server_timeout_title">"Zäitiwwerschreidung beim Server"</string>
+    <string name="server_timeout_message">"Nees mam Server verbanne fir de Video ofzespillen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connectioun feelgeschloen, probéieren nees mat %1$d ze verbannen\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Gëtt ofgespillt</string>
+    <string name="media_controller_connecting">Connectéieren\u2026</string>
+    <string name="bookmark_add">"Lieszeechen dobäisetzen"</string>
+    <string name="bookmark_display">"Lieszeechen uweisen"</string>
+    <string name="bookmark_empty">"Keng Lieszeechen"</string>
+    <string name="bookmark_exist">"Lieszeechen existéiert schonn"</string>
+    <string name="bookmark_add_success">"Lieszeechen dobäigesat"</string>
+    <string name="bookmark_list">"Lieszeechen"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Standuert"</string>
+    <string name="delete_all">"All läschen"</string>
+    <string name="default_title">"Standardtitel"</string>
+    <string name="more_image">Méi Biller</string>
+    <string name="mute_nosupport">Kann net roueg schalten: Video net ënnerstëtzt</string>
+    <string name="map_activity_not_found_err">Et ass keng Kaarten-App installéiert fir d\'Positioun unzeweisen.</string>
+    <string name="fail_trim">Dëse Video ka leider net geschnidde ginn</string>
+    <string name="drm_license_info">DRM-Lizenzinformatiounen</string>
+</resources>
diff --git a/res/values-lb/filtershow_strings.xml b/res/values-lb/filtershow_strings.xml
new file mode 100644
index 0000000..4011a76
--- /dev/null
+++ b/res/values-lb/filtershow_strings.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">Fotoediteur</string>
+    <string name="cannot_load_image">D\'Bild kann net geluede ginn!</string>
+    <string name="cannot_edit_original">Original kann net geännert ginn</string>
+    <string name="setting_wallpaper">Als Hannergrondbild setzen</string>
+    <string name="download_failure">Konnt d\'Foto net eroflueden. D\'Netzwierk ass net disponibel.</string>
+    <string name="original">Original</string>
+    <string name="custom_border">Personaliséiert</string>
+    <string name="filtershow_undo">Réckgängeg maachen</string>
+    <string name="filtershow_redo">Widderhuelen</string>
+    <string name="show_imagestate_panel">Applizéiert Effekter uweisen</string>
+    <string name="hide_imagestate_panel">Applizéiert Effekter verstoppen</string>
+    <string name="export_image">Exportéieren</string>
+    <string name="print_image">Drécken</string>
+    <string name="export_flattened">Plattgemaacht Bild exportéieren</string>
+    <string name="select_output_settings">Das exportéiert Bild gëtt als Kopie gespäichert, ouni Historique.</string>
+    <string name="quality">Qualitéit</string>
+    <string name="size">Gréisst</string>
+    <string name="x">x</string>
+    <string name="menu_settings">Astellungen</string>
+    <string name="unsaved">Et ginn ongespäichert Ännerungen un dësem Bild.</string>
+    <string name="save_before_exit">Wëlls du d\'Bild virum Zoumaache späicheren?</string>
+    <string name="save_and_exit">Späicheren an zoumaachen</string>
+    <string name="save_and_processing">Bild mat voller Opléisung gëtt beaarbecht...</string>
+    <string name="exit">Verloossen</string>
+    <string name="history">Historique</string>
+    <string name="reset">Zrécksetzen</string>
+    <string name="history_original">@string/original</string>
+    <string name="imageState">Applizéiert Effekter</string>
+    <string name="compare_original">Vergläichen</string>
+    <string name="apply_effect">Applizéieren</string>
+    <string name="reset_effect">Zrécksetzen</string>
+    <string name="aspect">Aspekt</string>
+    <string name="aspect1to1_effect">1:1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">Keen</string>
+    <string name="Fixed">Fixéiert</string>
+    <string name="tinyplanet">Klenge Planéit</string>
+    <string name="exposure" msgid="1229093066434614811">Beliichtung</string>
+    <string name="sharpness">Schäerft</string>
+    <string name="contrast">Kontrast</string>
+    <string name="vibrance">Intensitéit</string>
+    <string name="saturation">Sättegung</string>
+    <string name="bwfilter">SW-Filter</string>
+    <string name="wbalance">Automatesch Faarwen</string>
+    <string name="hue">Faarftoun</string>
+    <string name="shadow_recovery">Déiften</string>
+    <string name="highlight_recovery">Héichten</string>
+    <string name="curvesRGB">Kurven</string>
+    <string name="vignette">Vignettéierung</string>
+    <string name="vignette_main">Vignettéierung</string>
+    <string name="vignette_exposure">Beliichtung</string>
+    <string name="vignette_saturation">Sättegung</string>
+    <string name="vignette_contrast">Kontrast</string>
+    <string name="vignette_falloff">Luuchtoffall</string>
+    <string name="redeye">Rout Aen</string>
+    <string name="imageDraw">Zeechnen</string>
+    <string name="straighten" msgid="5217801513491493491">Ausriichten</string>
+    <string name="crop" msgid="5584000454518174632">Schneiden</string>
+    <string name="rotate" msgid="460017689320955494">Rotéieren</string>
+    <string name="mirror">Spiggelen</string>
+    <string name="negative">Negativ</string>
+    <string name="none" msgid="3601545724573307541">Keen</string>
+    <string name="edge">Kanten</string>
+    <string name="kmeans">Posteriséiert</string>
+    <string name="downsample">Verklengeren</string>
+    <string name="grad">Ofgestuft</string>
+    <string name="editor_grad_brightness">Hellegkeet</string>
+    <string name="editor_grad_contrast">Kontrast</string>
+    <string name="editor_grad_saturation">Sättegung</string>
+    <string name="editor_chan_sat_main">Haapt</string>
+    <string name="editor_chan_sat_red">Rout</string>
+    <string name="editor_chan_sat_yellow">Giel</string>
+    <string name="editor_chan_sat_green">Gréng</string>
+    <string name="editor_chan_sat_cyan">Cyan</string>
+    <string name="editor_chan_sat_blue">Blo</string>
+    <string name="editor_chan_sat_magenta">Magenta</string>
+    <string name="editor_grad_style">Stil</string>
+    <string name="editor_grad_new">nei</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">Rout</string>
+    <string name="curves_channel_green">Gréng</string>
+    <string name="curves_channel_blue">Blo</string>
+    <string name="draw_style">Stil</string>
+    <string name="draw_size">Gréisst</string>
+    <string name="draw_hue">Faarftoun</string>
+    <string name="draw_saturation">Sättegung</string>
+    <string name="draw_value">Hellegkeet</string>
+    <string name="draw_color">Faarf</string>
+    <string name="draw_style_line">Linnen</string>
+    <string name="draw_style_brush_spatter">Filzstëft</string>
+    <string name="draw_style_brush_marker">Sprëtzer</string>
+    <string name="draw_clear">Eidel maachen</string>
+    <string name="color_border_size">Randstäerkt</string>
+    <string name="color_border_corner_size">Eckegréisst</string>
+    <string name="color_border_color">Faarf</string>
+    <string name="color_border_clear">Eidel maachen</string>
+    <string name="color_pick_select">Eege Faarf auswielen</string>
+    <string name="color_pick_title">Faarf auswielen</string>
+    <string name="draw_size_title">Gréisst auswielen</string>
+    <string name="draw_size_accept">OK</string>
+    <string name="state_panel_original">Original</string>
+    <string name="state_panel_result">Resultat</string>
+    <string name="filtershow_notification_label">Bild gëtt gespäichert</string>
+    <string name="filtershow_notification_message">Gëtt beaarbecht...</string>
+    <string name="filtershow_save_preset">Aktuell Virastellung späicheren</string>
+    <string name="filtershow_manage_preset">Benotzervirastellungen</string>
+    <string name="filtershow_new_preset">Nei Virastellung</string>
+    <string name="filtershow_preset_name">Virastellungsnumm</string>
+    <string name="filtershow_show_info_panel">Informatioun</string>
+    <string name="filtershow_show_info_panel_name">Bildnumm</string>
+    <string name="filtershow_show_info_panel_size">Bildgréisst</string>
+    <string name="filtershow_show_info_panel_histogram">Histogramm</string>
+    <string name="filtershow_show_info_panel_exif">EXIF-Daten</string>
+    <string name="filtershow_add_button_looks">Virastellung</string>
+    <string name="filtershow_add_button_versions">Versioun</string>
+    <string name="filtershow_version_original">Original</string>
+    <string name="filtershow_version_current">Aktuell</string>
+    <string name="filtershow_exif_model">Modell</string>
+    <string name="filtershow_exif_aperture">Blend</string>
+    <string name="filtershow_exif_focal_length">Brennwäit</string>
+    <string name="filtershow_exif_iso">ISO</string>
+    <string name="filtershow_exif_subject_distance">Distanz zum Sujet</string>
+    <string name="filtershow_exif_date">Ophueldatum</string>
+    <string name="filtershow_exif_f_stop">Blendenzuel</string>
+    <string name="filtershow_exif_exposure_time">Beliichtungszäit</string>
+    <string name="filtershow_exif_copyright">Auteursrecht</string>
+</resources>
diff --git a/res/values-lb/strings.xml b/res/values-lb/strings.xml
new file mode 100644
index 0000000..be5da5c
--- /dev/null
+++ b/res/values-lb/strings.xml
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">Galerie</string>
+    <string name="gadget_title">Billerrumm</string>
+    <string name="details_ms">%1$02d:%2$02d</string>
+    <string name="details_hms">%1$d:%2$02d:%3$02d</string>
+    <string name="movie_view_label">Videoofspiller</string>
+    <string name="loading_video">Video gëtt gelueden\u2026</string>
+    <string name="loading_image">Bild gëtt gelueden\u2026</string>
+    <string name="loading_account">Kont gëtt gelueden\u2026</string>
+    <string name="resume_playing_title">Video weiderspillen</string>
+    <string name="resume_playing_message">Bei %s weider ofspillen?</string>
+    <string name="resume_playing_resume">Weider ofspillen</string>
+    <string name="loading">Gëtt gelueden\u2026</string>
+    <string name="fail_to_load">Konnt net lueden</string>
+    <string name="fail_to_load_image">D\'Bild konnt net geluede ginn</string>
+    <string name="no_thumbnail">Kee Virschaubild</string>
+    <string name="resume_playing_restart">Vu vir ufänken</string>
+    <string name="crop_save_text">OK</string>
+    <string name="ok">OK</string>
+    <string name="multiface_crop_help">E Gesiicht drécke fir unzefänken.</string>
+    <string name="saving_image">Bild gëtt gespäichert\u2026</string>
+    <string name="filtershow_saving_image">D\'Bild gëtt an den Album <xliff:g id="album_name">%1$s</xliff:g> gespäichert\u2026</string>
+    <string name="save_error">Konnt dat geschniddent Bild net späicheren.</string>
+    <string name="crop_label">Bild schneiden</string>
+    <string name="trim_label">Video kierzen</string>
+    <string name="select_image">Foto auswielen</string>
+    <string name="select_video">Video auswielen</string>
+    <string name="select_item">Element auswielen</string>
+    <string name="select_album">Album auswielen</string>
+    <string name="select_group">Grupp auswielen</string>
+    <string name="set_image">Bild setzen als</string>
+    <string name="set_wallpaper">Hannergrondbild setzen</string>
+    <string name="wallpaper">Hannergrondbild gëtt gesat\u2026</string>
+    <string name="camera_setas_wallpaper">Hannergrondbild</string>
+    <string name="delete">Läschen</string>
+    <plurals name="delete_selection">
+        <item quantity="one">Ausgewielt Element läschen?</item>
+        <item quantity="other">Ausgewielt Elementer läschen?</item>
+    </plurals>
+    <string name="confirm">Bestätegen</string>
+    <string name="cancel">Ofbriechen</string>
+    <string name="share">Deelen</string>
+    <string name="share_panorama">Panorama deelen</string>
+    <string name="share_as_photo">Als Foto deelen</string>
+    <string name="deleted">Geläscht</string>
+    <string name="undo">RÉCKGÄNGEG</string>
+    <string name="select_all">All auswielen</string>
+    <string name="deselect_all">Auswiel ophiewen</string>
+    <string name="slideshow">Diashow</string>
+    <string name="details">Detailer</string>
+    <string name="details_title">%1$d / %2$d Elementer:</string>
+    <string name="close">Zoumaachen</string>
+    <string name="switch_to_camera">Op d\'Kamera wiesselen</string>
+    <plurals name="number_of_items_selected">
+        <item quantity="one">%1$d ausgewielt</item>
+        <item quantity="other">%1$d ausgewielt</item>
+    </plurals>
+    <plurals name="number_of_albums_selected">
+        <item quantity="one">%1$d ausgewielt</item>
+        <item quantity="other">%1$d ausgewielt</item>
+    </plurals>
+    <plurals name="number_of_groups_selected">
+        <item quantity="one">%1$d ausgewielt</item>
+        <item quantity="other">%1$d ausgewielt</item>
+    </plurals>
+    <string name="show_on_map">Op der Kaart uweisen</string>
+    <string name="rotate_left">Lénks rotéieren</string>
+    <string name="rotate_right">Riets rotéieren</string>
+    <string name="no_such_item">Konnt d\'Element net fannen.</string>
+    <string name="edit">Beaarbechten</string>
+    <string name="simple_edit">Einfach Beaarbechtung</string>
+    <string name="process_caching_requests">Tëschespäicherungsufroe gi veraarbecht</string>
+    <string name="caching_label">Tëschespäicherung leeft\u2026</string>
+    <string name="crop_action">Schneiden</string>
+    <string name="trim_action">Trimmen</string>
+    <string name="mute_action">Roueg</string>
+    <string name="set_as">Setzen als</string>
+    <string name="video_mute_err">Kann de Video net roueg schalten.</string>
+    <string name="video_err">Video kann net ofgespillt ginn.</string>
+    <string name="group_by_location">No Plaz</string>
+    <string name="group_by_time">No Zäit</string>
+    <string name="group_by_tags">No Etiketten</string>
+    <string name="group_by_faces">No Leit</string>
+    <string name="group_by_album">No Album</string>
+    <string name="group_by_size">No Gréisst</string>
+    <string name="untagged">Ouni Etikett</string>
+    <string name="no_location">Keng Plaz</string>
+    <string name="no_connectivity">E puer Plaze konnte wéinst Netzwierkproblemer net identifizéiert ginn.</string>
+    <string name="sync_album_error">Konnt d\'Fotoen aus dësem Album net eroflueden. Probéier méi spéit nees.</string>
+    <string name="show_images_only">Just Biller</string>
+    <string name="show_videos_only">Just Videoen</string>
+    <string name="show_all">Biller a Videoen</string>
+    <string name="appwidget_title">Fotogalerie</string>
+    <string name="appwidget_empty_text">Keng Fotoen.</string>
+    <string name="crop_saved">Geschniddent Bild gespäichert ënner <xliff:g id="folder_name">%s</xliff:g>.</string>
+    <string name="no_albums_alert">Keng Alben disponibel.</string>
+    <string name="empty_album">O Biller/Videoen disponibel.</string>
+    <string name="picasa_posts">Posts</string>
+    <string name="make_available_offline">Offline disponibel maachen</string>
+    <string name="sync_picasa_albums">Opfrëschen</string>
+    <string name="done">Fäerdeg</string>
+    <string name="sequence_in_set">%1$d / %2$d Elementer:</string>
+    <string name="title">Titel</string>
+    <string name="description">Beschreiwung</string>
+    <string name="time">Zäit</string>
+    <string name="location">Standuert</string>
+    <string name="path">Pad</string>
+    <string name="width">Breet</string>
+    <string name="height">Héicht</string>
+    <string name="orientation">Orientéierung</string>
+    <string name="duration">Dauer</string>
+    <string name="mimetype">MIME-Typ</string>
+    <string name="file_size">Fichiersgréisst</string>
+    <string name="maker">Hiersteller</string>
+    <string name="model">Modell</string>
+    <string name="flash">Blëtz</string>
+    <string name="aperture">Blend</string>
+    <string name="focal_length">Brennwäit</string>
+    <string name="white_balance">Wäissofgläich</string>
+    <string name="exposure_time">Beliichtungszäit</string>
+    <string name="iso">ISO</string>
+    <string name="unit_mm">mm</string>
+    <string name="manual">Manuell</string>
+    <string name="auto">Automatesch</string>
+    <string name="flash_on">Blëtz ausgeléist</string>
+    <string name="flash_off">Kee Blëtz</string>
+    <string name="unknown">Onbekannt</string>
+    <string name="ffx_original">Original</string>
+    <string name="ffx_vintage">Almoudesch</string>
+    <string name="ffx_instant">Direktbild</string>
+    <string name="ffx_bleach">Verbleecht</string>
+    <string name="ffx_blue_crush">Blo</string>
+    <string name="ffx_bw_contrast">S/W</string>
+    <string name="ffx_punch">Punch</string>
+    <string name="ffx_x_process">X Process</string>
+    <string name="ffx_washout">Latte</string>
+    <string name="ffx_washout_color">Litho</string>
+    <plurals name="make_albums_available_offline">
+        <item quantity="one">Den Album gëtt offline disponibel gemaach.</item>
+        <item quantity="other">D\'Albe ginn offline disponibel gemaach.</item>
+    </plurals>
+    <string name="try_to_set_local_album_available_offline">Dëst Element ass lokal gespäichert an och offiline disponibel.</string>
+    <string name="set_label_all_albums">All d\'Alben</string>
+    <string name="set_label_local_albums">Lokal Alben</string>
+    <string name="set_label_mtp_devices">MTP-Apparater</string>
+    <string name="set_label_picasa_albums">Picasa-Alben</string>
+    <string name="free_space_format"><xliff:g id="bytes">%s</xliff:g> fräi</string>
+    <string name="size_below"><xliff:g id="size">%1$s</xliff:g> oder drënner</string>
+    <string name="size_above"><xliff:g id="size">%1$s</xliff:g> oder driwwer</string>
+    <string name="size_between"><xliff:g id="min_size">%1$s</xliff:g> bis <xliff:g id="max_size">%2$s</xliff:g></string>
+    <string name="Import">Importéieren</string>
+    <string name="import_complete">Import ofgeschloss</string>
+    <string name="import_fail">Import feelgeschloen</string>
+    <string name="camera_connected">Kamera connectéiert.</string>
+    <string name="camera_disconnected">Kamera deconnectéiert.</string>
+    <string name="click_import">Hei drécke fir z\'importéieren</string>
+    <string name="widget_type_album">En Album auswielen</string>
+    <string name="widget_type_shuffle">All d\'Biller mëschen</string>
+    <string name="widget_type_photo">E Bild auswielen</string>
+    <string name="widget_type">Biller auswielen</string>
+    <string name="slideshow_dream_name">Diashow</string>
+    <string name="albums">Alben</string>
+    <string name="times">Zäiten</string>
+    <string name="locations">Plazen</string>
+    <string name="people">Leit</string>
+    <string name="tags">Etiketten</string>
+    <string name="group_by">Gruppéieren no</string>
+    <string name="settings">Astellungen</string>
+    <string name="add_account">Kont dobäisetzen</string>
+    <string name="folder_camera">Fotoapparat</string>
+    <string name="folder_download">Erofgelueden</string>
+    <string name="folder_edited_online_photos">Beaarbecht Online-Fotoen</string>
+    <string name="folder_imported">Importéiert</string>
+    <string name="folder_screenshot">Schiermfoto</string>
+    <string name="help">Hëllef</string>
+    <string name="no_external_storage_title">Kee Späicher</string>
+    <string name="no_external_storage">Keen externe Späicher disponibel</string>
+    <string name="switch_photo_filmstrip">Als Filmsträif uweisen</string>
+    <string name="switch_photo_grid">Gitterusiicht</string>
+    <string name="switch_photo_fullscreen">Vollschierm-Usiicht</string>
+    <string name="trimming">Gëtt geschnidden</string>
+    <string name="muting">Toun gëtt ausgeschalt</string>
+    <string name="please_wait">W.e.g. waarden</string>
+    <string name="save_into">De Video gëtt an den Album <xliff:g id="album_name">%1$s</xliff:g> gespäichert\u2026</string>
+    <string name="trim_too_short">Kann net kierzen: den Zilvideo ass ze kuerz</string>
+    <string name="pano_progress_text">Panorama gëtt gerendert</string>
+    <string name="save" msgid="8140440041190264400">Späicheren</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">Inhalt gëtt gescannt...</string>
+    <plurals name="ingest_number_of_items_scanned">
+        <item quantity="one">%1$d Element gescannt</item>
+        <item quantity="other">%1$d Elementer gescannt</item>
+    </plurals>
+    <plurals name="ingest_number_of_items_selected">
+        <item quantity="one">%1$d Element ausgewielt</item>
+        <item quantity="other">%1$d Elementer ausgewielt</item>
+    </plurals>
+    <string name="ingest_sorting" msgid="624687230903648118">Gëtt zortéiert...</string>
+    <string name="ingest_scanning_done">Scannen ofgeschloss</string>
+    <string name="ingest_importing">Gëtt importéiert...</string>
+    <string name="ingest_empty_device">Et ass keen Inhalt op dësem Apparat disponibel deen importéiert ka ginn.</string>
+    <string name="ingest_no_device">Et si keng MTP-Apparater connectéiert</string>
+    <string name="camera_error_title">Kamerafeeler</string>
+    <string name="cannot_connect_camera">Keng Connectioun zur Kamera méiglech.</string>
+    <string name="camera_disabled">D\'Kamera gouf wéinst Sécherheetsriichtlinnen desaktivéiert.</string>
+    <string name="camera_label">Fotoapparat</string>
+    <string name="wait">Waart w.e.g.\u2026</string>
+    <string name="no_storage" product="nosdcard">Bann den USB-Späicher an ier s de d\'Kamera benotz.</string>
+    <string name="no_storage" product="default">Maach eng SD-Kaart dran ier s du d\'Kamera benotzt.</string>
+    <string name="preparing_sd" product="nosdcard">USB-Späicher gëtt preparéiert\u2026</string>
+    <string name="preparing_sd" product="default">SD-Kaart gëtt preparéiert\u2026</string>
+    <string name="access_sd_fail" product="nosdcard">Keen Zougrëff op den USB-Späicher méiglech.</string>
+    <string name="access_sd_fail" product="default">Keen Zougrëff op d\'SD-Kaart méiglech.</string>
+    <string name="review_cancel">OFBRIECHEN</string>
+    <string name="review_ok">FÄERDEG</string>
+    <string name="time_lapse_title">Zäitrafferopnam</string>
+    <string name="pref_camera_id_title">Kamera wielen</string>
+    <string name="pref_camera_id_entry_back">Hannen</string>
+    <string name="pref_camera_id_entry_front">Vir</string>
+    <string name="pref_camera_recordlocation_title">Plaz späicheren</string>
+    <string name="pref_camera_location_label">PLAZ</string>
+    <string name="pref_camera_timer_title">Countdown-Timer</string>
+    <plurals name="pref_camera_timer_entry">
+        <item quantity="one">1 Sekonn</item>
+        <item quantity="other">%d Sekonnen</item>
+    </plurals>
+    <string name="pref_camera_timer_sound_default">@string/setting_on_value</string>
+    <string name="pref_camera_timer_sound_title">Piipse während dem Countdown</string>
+    <string name="setting_off">Aus</string>
+    <string name="setting_on">Un</string>
+    <string name="pref_video_quality_title">Videoqualitéit</string>
+    <string name="pref_video_quality_entry_high">Héich</string>
+    <string name="pref_video_quality_entry_low">Niddreg</string>
+    <string name="pref_video_time_lapse_frame_interval_title">Zäitraffer</string>
+    <string name="pref_camera_settings_category">Kameraastellungen</string>
+    <string name="pref_camcorder_settings_category">Kameraastellungen</string>
+    <string name="pref_camera_picturesize_title">Fotogréisst</string>
+    <string name="pref_camera_picturesize_entry_13mp">13M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_8mp">8M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_5mp">5M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_4mp">4M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_3mp">3M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_2mp">2M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">2M Pixelen (16:9)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">1,3M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_1mp">1M Pixelen</string>
+    <string name="pref_camera_picturesize_entry_vga">VGA</string>
+    <string name="pref_camera_picturesize_entry_qvga">QVGA</string>
+    <string name="pref_camera_focusmode_title">Fokusmodus</string>
+    <string name="pref_camera_focusmode_entry_auto">Automatesch</string>
+    <string name="pref_camera_focusmode_entry_infinity">Onendlech</string>
+    <string name="pref_camera_focusmode_entry_macro">Makro</string>
+    <string name="pref_camera_focusmode_label_auto">AUTO</string>
+    <string name="pref_camera_focusmode_label_infinity">ONENDLECH</string>
+    <string name="pref_camera_focusmode_label_macro">MAKRO</string>
+    <string name="pref_camera_flashmode_title">Blëtzmodus</string>
+    <string name="pref_camera_flashmode_label">BLËTZMODUS</string>
+    <string name="pref_camera_flashmode_entry_auto">Automatesch</string>
+    <string name="pref_camera_flashmode_entry_on">Un</string>
+    <string name="pref_camera_flashmode_entry_off">Aus</string>
+    <string name="pref_camera_flashmode_label_auto">BLËTZ AUTO</string>
+    <string name="pref_camera_flashmode_label_on">BLËTZ UN</string>
+    <string name="pref_camera_flashmode_label_off">BLËTZ AUS</string>
+    <string name="pref_camera_whitebalance_title">Wäissofgläich</string>
+    <string name="pref_camera_whitebalance_label">WÄISSOFGLÄICH</string>
+    <string name="pref_camera_whitebalance_entry_auto">Automatesch</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">Glousluucht</string>
+    <string name="pref_camera_whitebalance_entry_daylight">Dagesliicht</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">Fluoreszent</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">Wollekeg</string>
+    <string name="pref_camera_whitebalance_label_auto">AUTO</string>
+    <string name="pref_camera_whitebalance_label_incandescent">GLOUSLUUCHT</string>
+    <string name="pref_camera_whitebalance_label_daylight">DAGESLIICHT</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">FLUORESZENT</string>
+    <string name="pref_camera_whitebalance_label_cloudy">WOLLEKEG</string>
+    <string name="pref_camera_scenemode_title">Zeenemodus</string>
+    <string name="pref_camera_scenemode_entry_auto">Automatesch</string>
+    <string name="pref_camera_scenemode_entry_hdr">HDR</string>
+    <string name="pref_camera_scenemode_entry_action">Aktioun</string>
+    <string name="pref_camera_scenemode_entry_night">Nuecht</string>
+    <string name="pref_camera_scenemode_entry_sunset">Sonnenënnergank</string>
+    <string name="pref_camera_scenemode_entry_party">Party</string>
+    <string name="pref_camera_scenemode_label_auto">KEEN</string>
+    <string name="pref_camera_scenemode_label_action">AKTIOUN</string>
+    <string name="pref_camera_scenemode_label_night">NUECHT</string>
+    <string name="pref_camera_scenemode_label_sunset">SONNENËNNERGANK</string>
+    <string name="pref_camera_scenemode_label_party">PARTY</string>
+    <string name="pref_camera_countdown_label">SANDAUER</string>
+    <string name="pref_camera_countdown_label_off">TIMER AUS</string>
+    <string name="pref_camera_countdown_label_one">1 SEKONN</string>
+    <string name="pref_camera_countdown_label_three">3 SEKONNEN</string>
+    <string name="pref_camera_countdown_label_ten">10 SEKONNEN</string>
+    <string name="pref_camera_countdown_label_fifteen">15 SEKONNEN</string>
+    <string name="not_selectable_in_scene_mode">Dës Astellung kann am Zeenemodus net ausgewielt ginn.</string>
+    <string name="pref_exposure_title">Beliichtung</string>
+    <string name="pref_exposure_label">BELIICHTUNG</string>
+    <string name="pref_camera_hdr_default">@string/setting_off_value</string>
+    <string name="pref_camera_hdr_label">HDR</string>
+    <string name="pref_camera_id_label_back">VIISCHT KAMERA</string>
+    <string name="pref_camera_id_label_front">HËNNESCHT KAMERA</string>
+    <string name="dialog_ok">OK</string>
+    <string name="spaceIsLow_content" product="nosdcard">Däin USB-Späicher huet geschwë keng Plaz méi. Änner d\'Qualitéitsastellungen oder läsch e puer Fotoen oder aner Fichieren.</string>
+    <string name="spaceIsLow_content" product="default">Deng SD-Kaart huet geschwë keng Plaz méi. Änner d\'Qualitéitsastellungen oder läsch e puer Fotoen oder Fichieren.</string>
+    <string name="video_reach_size_limit">Gréisstelimitt ass erreecht.</string>
+    <string name="pano_too_fast_prompt">Ze séier</string>
+    <string name="pano_dialog_prepare_preview">Panorama gëtt preparéiert</string>
+    <string name="pano_dialog_panorama_failed">De Panorama konnt net gespäichert ginn.</string>
+    <string name="pano_dialog_title">Panorama</string>
+    <string name="pano_capture_indication">Panorama gëtt opgeholl</string>
+    <string name="pano_dialog_waiting_previous">Waarden op dee Panorama virdrun</string>
+    <string name="pano_review_saving_indication_str">Gëtt gespäichert\u2026</string>
+    <string name="pano_review_rendering">Panorama gëtt gerendert</string>
+    <string name="tap_to_focus">Drécke fir schaarf ze stellen.</string>
+    <string name="pref_video_effect_title">Effekter</string>
+    <string name="effect_none">Keen</string>
+    <string name="effect_goofy_face_squeeze">Quëtschen</string>
+    <string name="effect_goofy_face_big_eyes">Grouss Aen</string>
+    <string name="effect_goofy_face_big_mouth">Grousse Mond</string>
+    <string name="effect_goofy_face_small_mouth">Klenge Mond</string>
+    <string name="effect_goofy_face_big_nose">Grouss Nues</string>
+    <string name="effect_goofy_face_small_eyes">Kleng Aen</string>
+    <string name="effect_backdropper_space">Am Weltraum</string>
+    <string name="effect_backdropper_sunset">Sonnenënnergank</string>
+    <string name="effect_backdropper_gallery">Däi Video</string>
+    <string name="bg_replacement_message">Lee däin Apparat of.\nTriet e Moment aus dem Siichtberäich.</string>
+    <string name="video_snapshot_hint">Drécke fir Fotoen ze maache während s du films.</string>
+    <string name="video_recording_started">Videoopnam gouf gestart.</string>
+    <string name="video_recording_stopped">Videoopnam gouf opgehalen.</string>
+    <string name="disable_video_snapshot_hint">Video-Schnappschoss ass bei Spezialeffekter desaktivéiert.</string>
+    <string name="clear_effects">Effekter ewechhuelen</string>
+    <string name="effect_silly_faces">LËSCHTEG GESIICHTER</string>
+    <string name="effect_background">HANNERGROND</string>
+    <string name="accessibility_shutter_button">Ausléisknäppchen</string>
+    <string name="accessibility_menu_button">Menü-Knäppchen</string>
+    <string name="accessibility_review_thumbnail">Rezentst Foto</string>
+    <string name="accessibility_camera_picker">Tëscht de Kamerae vir an hanne wiesselen</string>
+    <string name="accessibility_mode_picker">Auswiel fir Fotoapparat, Video oder Panorama</string>
+    <string name="accessibility_second_level_indicators">Weider Astellungen</string>
+    <string name="accessibility_back_to_first_level">Astellungen zoumaachen</string>
+    <string name="accessibility_zoom_control">Zoomsteierung</string>
+    <string name="accessibility_decrement">%1$s erofsetzen</string>
+    <string name="accessibility_increment">%1$s eropsetzen</string>
+    <string name="accessibility_check_box">%1$s Ukräizfeld</string>
+    <string name="accessibility_switch_to_camera">Op de Foto-Modus wiesselen</string>
+    <string name="accessibility_switch_to_video">Op de Video-Modus wiesselen</string>
+    <string name="accessibility_switch_to_panorama">Op de Panorama-Modus wiesselen</string>
+    <string name="accessibility_switch_to_new_panorama">Bei den neie Panorama wiesselen</string>
+    <string name="accessibility_switch_to_refocus">Bei d\'Auswiel vun engem neie Fokus wiesselen</string>
+    <string name="accessibility_review_cancel">Iwwerpréiwung ofbriechen</string>
+    <string name="accessibility_review_ok">Iwwerpréiwung ofgeschloss</string>
+    <string name="accessibility_review_retake">Iwwerpréiwung - Nei Ophuelen</string>
+    <string name="accessibility_play_video">Video ofspillen</string>
+    <string name="accessibility_pause_video">Video pauséieren</string>
+    <string name="accessibility_reload_video">Video nei lueden</string>
+    <string name="accessibility_time_bar">Zäitlinn vum Videoofspiller</string>
+    <string name="capital_on">UN</string>
+    <string name="capital_off">AUS</string>
+    <string name="pref_video_time_lapse_frame_interval_off">Aus</string>
+    <string name="pref_video_time_lapse_frame_interval_500">0,5 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 Sekonn</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">1,5 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2,5 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 Sekonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">0,5 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">1 Minutt</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">1,5 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2,5 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 Minutten</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">0,5 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 Stonn</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">1,5 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2,5 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 Stonnen</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 Stonnen</string>
+    <string name="time_lapse_seconds">Sekonnen</string>
+    <string name="time_lapse_minutes">Minutten</string>
+    <string name="time_lapse_hours">Stonnen</string>
+    <string name="time_lapse_interval_set">Fäerdeg</string>
+    <string name="set_time_interval">Zäitintervall setzen</string>
+    <string name="set_time_interval_help">Zäitrafferfunktioun ass aus. Maach s\'u fir den Zäitintervall ze setzen.</string>
+    <string name="set_timer_help">D\'Sandauer ass aus. Schalt s\'u fir erofzezielen ier eng Foto gemaach gëtt.</string>
+    <string name="set_duration">Dauer a Sekonne festleeën</string>
+    <string name="count_down_title_text">Countdown fir eng Foto ze schéissen</string>
+    <string name="remember_location_title">De Fotostanduert späicheren?</string>
+    <string name="remember_location_prompt">Fotoen a Videoe mam Standuert späichere wou s\'opgeholl gi sinn.\n\nAner Appe kënnen zesumme mat de gespäicherte Biller op dës Informatioun zougräifen.</string>
+    <string name="remember_location_no">Nee Merci</string>
+    <string name="remember_location_yes">Jo</string>
+    <string name="menu_camera">Fotoapparat</string>
+    <string name="menu_search">Sichen</string>
+    <string name="tab_photos">Fotoen</string>
+    <string name="tab_albums">Alben</string>
+    <string name="camera_menu_more_label">MÉI OPTIOUNEN</string>
+    <string name="camera_menu_settings_label">ASTELLUNGEN</string>
+    <plurals name="number_of_photos">
+        <item quantity="one">%1$d Foto</item>
+        <item quantity="other">%1$d Fotoen</item>
+    </plurals>
+</resources>
diff --git a/res/values-lt/cm_strings.xml b/res/values-lt/cm_strings.xml
new file mode 100644
index 0000000..93bb8f7
--- /dev/null
+++ b/res/values-lt/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Įrašo laikas</string>
+</resources>
diff --git a/res/values-lt/codeaurora_strings.xml b/res/values-lt/codeaurora_strings.xml
new file mode 100644
index 0000000..e98839a
--- /dev/null
+++ b/res/values-lt/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Žingsnis</string>
+    <string name="step_option_desc">Tinkinti greito prasukimo / atsukimo žingsnį</string>
+    <string name="setp_option_three_second">3 sek.</string>
+    <string name="setp_option_six_second">6 sek.</string>
+    <string name="loop">"Ciklas"</string>
+    <string name="single">"Vientisas"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Garsiakalbis ĮJUNGTAS</string>
+    <string name="speaker_off">Garsiakalbis IŠJUNGTAS</string>
+    <string name="speaker_need_headset">Prijunkite ausines, kad naudotumėtes šia funkcija.</string>
+    <string name="single_track">"Vienas takelis"</string>
+    <string name="input_url">"Įveskite URL"</string>
+    <string name="streaming_settings">"Srautinių transliacijų nustatymai"</string>
+    <string name="next">"Kitas"</string>
+    <string name="previous">"Ankstesnis"</string>
+    <string name="buffer_size">Buferio dydis</string>
+    <string name="apn">Pageidaujamas APN</string>
+    <string name="rtp_min_port">Mažiausias prievadas</string>
+    <string name="rtp_max_port">Didžiausias prievadas</string>
+    <string name="set_rtp_min_port">Nustatyti mažiausią prievadą</string>
+    <string name="set_rtp_max_port">Nustatyti didžiausią prievadą</string>
+    <string name="set_buffer_size">Nustatyti buferio dydį</string>
+    <string name="set_apn">Pasirinkti pageidaujamą APN</string>
+    <string name="setting">Nustatymai</string>
+    <string name="server_timeout_title">"Serverio skirtasis laikas"</string>
+    <string name="server_timeout_message">"Prisijungti prie serverio, kad paleisti vaizdo įrašą?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Prisijungimas nepavyko, bandoma prisijungti prie %1$d\u2026"</string>
+    <string name="media_controller_live">Tiesiogiai</string>
+    <string name="media_controller_playing">Leidžiama</string>
+    <string name="media_controller_connecting">Jungiamasi\u2026</string>
+    <string name="bookmark_add">"Pridėti žymę"</string>
+    <string name="bookmark_display">"Rodyti žymes"</string>
+    <string name="bookmark_empty">"Žymių nėra"</string>
+    <string name="bookmark_exist">"Žymė jau egzistuoja"</string>
+    <string name="bookmark_add_success">"Žymė pridėta"</string>
+    <string name="bookmark_list">"Žymės"</string>
+    <string name="bookmark_title">"Pavadinimas"</string>
+    <string name="bookmark_location">"Vietovė"</string>
+    <string name="delete_all">"Ištrinti visas"</string>
+    <string name="default_title">"Numatytasis pavadinimas"</string>
+    <string name="more_image">Daugiau vaizdų</string>
+    <string name="mute_nosupport">Negalima nutildyti: vaizdo įrašas nepalaikomas</string>
+    <string name="map_activity_not_found_err">Nėra įdiegtos žemėlapių programos tam, kad parodyti vietovę.</string>
+    <string name="fail_trim">Atsiprašome, šis vaizdo įrašas negali būti apkarpytas</string>
+    <string name="drm_license_info">DRM licencijos informacija</string>
+</resources>
diff --git a/res/values-lu/cm_strings.xml b/res/values-lu/cm_strings.xml
new file mode 100644
index 0000000..f159db5
--- /dev/null
+++ b/res/values-lu/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Opnamezäit</string>
+</resources>
diff --git a/res/values-lu/codeaurora_strings.xml b/res/values-lu/codeaurora_strings.xml
new file mode 100644
index 0000000..68e2b2b
--- /dev/null
+++ b/res/values-lu/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Schrëtt</string>
+    <string name="step_option_desc">Vir- an Zréckspull-Schrëtter upassen</string>
+    <string name="setp_option_three_second">3 Sekonnen</string>
+    <string name="setp_option_six_second">6 Sekonnen</string>
+    <string name="loop">"Widderhuelen"</string>
+    <string name="single">"Eenzel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Lautsprecher UN</string>
+    <string name="speaker_off">Lautsprecher AUS</string>
+    <string name="speaker_need_headset">Schléis Kopfhörer u fir dës Funktioun ze benotzen.</string>
+    <string name="single_track">"Eenzel Spur"</string>
+    <string name="input_url">"URL aginn"</string>
+    <string name="streaming_settings">"Streamingastellungen"</string>
+    <string name="next">"Weider"</string>
+    <string name="previous">"Zréck"</string>
+    <string name="buffer_size">Tëschespäicher-Gréisst</string>
+    <string name="apn">Preferéierten APN</string>
+    <string name="rtp_min_port">Min. Port</string>
+    <string name="rtp_max_port">Max. Port</string>
+    <string name="set_rtp_min_port">Min. Port festleeën</string>
+    <string name="set_rtp_max_port">Max. Port festleeën</string>
+    <string name="set_buffer_size">Tëschespäichergréisst definéieren</string>
+    <string name="set_apn">Preferéierten APN auswielen</string>
+    <string name="setting">Astellungen</string>
+    <string name="server_timeout_title">"Zäitiwwerschreidung beim Server"</string>
+    <string name="server_timeout_message">"Nees mam Server verbanne fir de Video ofzespillen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connectioun feelgeschloen, probéieren nees mat %1$d ze verbannen\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Gëtt ofgespillt</string>
+    <string name="media_controller_connecting">Connectéieren\u2026</string>
+    <string name="bookmark_add">"Lieszeechen dobäisetzen"</string>
+    <string name="bookmark_display">"Lieszeechen uweisen"</string>
+    <string name="bookmark_empty">"Keng Lieszeechen"</string>
+    <string name="bookmark_exist">"Lieszeechen existéiert schonn"</string>
+    <string name="bookmark_add_success">"Lieszeechen dobäigesat"</string>
+    <string name="bookmark_list">"Lieszeechen"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Standuert"</string>
+    <string name="delete_all">"All läschen"</string>
+    <string name="default_title">"Standardtitel"</string>
+    <string name="more_image">Méi Biller</string>
+    <string name="mute_nosupport">Kann net roueg schalten: Video net ënnerstëtzt</string>
+    <string name="map_activity_not_found_err">Et ass keng Kaarten-App installéiert fir d\'Positioun unzeweisen.</string>
+    <string name="fail_trim">Dëse Video ka leider net geschnidde ginn</string>
+    <string name="drm_license_info">DRM-Lizenzinformatiounen</string>
+</resources>
diff --git a/res/values-lv/cm_strings.xml b/res/values-lv/cm_strings.xml
new file mode 100644
index 0000000..4f4a30f
--- /dev/null
+++ b/res/values-lv/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Ieraksta laiks</string>
+</resources>
diff --git a/res/values-lv/codeaurora_strings.xml b/res/values-lv/codeaurora_strings.xml
new file mode 100644
index 0000000..c8d255e
--- /dev/null
+++ b/res/values-lv/codeaurora_strings.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Solis</string>
+    <string name="step_option_desc">Pielāgot ātro pārtīšanu turp/atpakaļ</string>
+    <string name="setp_option_three_second">3 sekundes</string>
+    <string name="setp_option_six_second">6 sekundes</string>
+    <string name="loop">"Cilpa"</string>
+    <string name="single">"Viens"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Skaļrunis ieslēgts</string>
+    <string name="speaker_off">Skaļrunis izslēgts</string>
+    <string name="speaker_need_headset">Lai lietotu šo iespēju, pievienojiet austiņas.</string>
+    <string name="single_track">"Viens kanāls"</string>
+    <string name="input_url">"Ievadiet URL"</string>
+    <string name="streaming_settings">"Straumēšanas iestatījumi"</string>
+    <string name="next">"Nākamais"</string>
+    <string name="previous">"Iepriekšējais"</string>
+    <string name="buffer_size">Bufera lielums</string>
+    <string name="apn">Vēlamais APN</string>
+    <string name="rtp_min_port">Min. ports</string>
+    <string name="rtp_max_port">Maks. ports</string>
+    <string name="set_rtp_min_port">Iestatīt min. portu</string>
+    <string name="set_rtp_max_port">Iestatīt maks. portu</string>
+    <string name="set_buffer_size">Iestatīt bufera lielumu</string>
+    <string name="set_apn">Izvēlieties vēlamo APN</string>
+    <string name="setting">Iestatījumi</string>
+    <string name="server_timeout_title">"Servera noildze"</string>
+    <string name="server_timeout_message">"Pārsavienoties ar serveri, lai atskaņotu video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Savienojus neizdevās, mēģinot pieslēgties %1$d\u2026"</string>
+    <string name="media_controller_live">Dzīvajā</string>
+    <string name="media_controller_playing">Spēlē</string>
+    <string name="media_controller_connecting">Savienojas\u2026</string>
+    <string name="bookmark_add">"Pievienot grāmatzīmi"</string>
+    <string name="bookmark_display">"Rādīt grāmatzīmes"</string>
+    <string name="bookmark_empty">"Nav grāmatzīmju"</string>
+    <string name="bookmark_exist">"Grāmatzīme jau pastāv"</string>
+    <string name="bookmark_add_success">"Grāmatzīme pievienota"</string>
+    <string name="bookmark_list">"Grāmatzīmes"</string>
+    <string name="bookmark_title">"Virsraksts"</string>
+    <string name="bookmark_location">"Atrašanās vieta"</string>
+    <string name="delete_all">"Dzēst visu"</string>
+    <string name="default_title">"Noklusētais virsraksts"</string>
+    <string name="more_image">Vairāk attēlu</string>
+    <string name="mute_nosupport">Nevar atslēgt skaņu: video nav atbalstīts</string>
+    <string name="map_activity_not_found_err">Atrašanās vietu nevar parādīt, jo nav uzstādīta kartes lietotne.</string>
+    <string name="fail_trim">Atvainojiet, šo video failu nevar apgriezt</string>
+</resources>
diff --git a/res/values-ml/cm_strings.xml b/res/values-ml/cm_strings.xml
new file mode 100644
index 0000000..6bb240e
--- /dev/null
+++ b/res/values-ml/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Record time</string>
+</resources>
diff --git a/res/values-ml/codeaurora_strings.xml b/res/values-ml/codeaurora_strings.xml
new file mode 100644
index 0000000..5de8827
--- /dev/null
+++ b/res/values-ml/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ഘട്ടം</string>
+    <string name="step_option_desc">ഫാസ്റ്റ് ഫോര്‍വേര്‍ഡ് / റീവൈന്‍ഡ് സ്റ്റെപ് ഇച്ഛാനുസൃതമാക്കുക</string>
+    <string name="setp_option_three_second">3 സെക്കൻഡ്</string>
+    <string name="setp_option_six_second">6 സെക്കൻഡ്</string>
+    <string name="loop">""ലൂപ്പുചെയ്യുക""</string>
+    <string name="single">""സിംഗിൾ""</string>
+    <string name="stereo">""സ്റ്റീരിയോ""</string>
+    <string name="speaker_on">സ്പീക്കർ ഓൺ</string>
+    <string name="speaker_off">സ്പീക്കർ ഓഫ്</string>
+    <string name="speaker_need_headset">ഈ സവിശേഷത ഉപയോഗിക്കാൻ ഹെഡ്ഫോണുകൾ ഘടിപ്പിക്കുക.</string>
+    <string name="single_track">""സിംഗിൾ ട്രാക്ക്""</string>
+    <string name="input_url">"“URL നൽകുക”"</string>
+    <string name="streaming_settings">""സ്ട്രീംചെയ്യൽ ക്രമീകരണം""</string>
+    <string name="next">""അടുത്തത്""</string>
+    <string name="previous">""മുമ്പത്തെ""</string>
+    <string name="buffer_size">ബഫർ വലുപ്പം</string>
+    <string name="apn">തിരഞ്ഞെടുത്ത പ്ലാൻ</string>
+    <string name="rtp_min_port">മിന്‍ പോർട്ട്</string>
+    <string name="rtp_max_port">മാക്സ് പോർട്ട്</string>
+    <string name="set_rtp_min_port">മിന്‍ പോർട്ട് സജ്ജമാക്കുക</string>
+    <string name="set_rtp_max_port">പരമാവധി പോർട്ട് സജ്ജമാക്കുക</string>
+    <string name="set_buffer_size">ബഫർ വലുപ്പം സജ്ജമാക്കുക</string>
+    <string name="set_apn">ഇഷ്ടമുള്ള APN തിരഞ്ഞെടുക്കുക</string>
+    <string name="setting">ക്രമീകരണം</string>
+    <string name="server_timeout_title">""സെർവർ കാലഹരണപ്പെട്ടു""</string>
+    <string name="server_timeout_message">"വീഡിയോ പ്ലേ ചെയ്യാന്‍ സെർവറിലേക്ക് വീണ്ടും ബന്ധിപ്പിക്കുക"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"കണക്ഷൻ പരാജയപ്പെട്ടു, %1$d\ ലേക്ക് വീണ്ടും ബന്ധിപ്പിക്കാൻ ശ്രമിക്കുന്നു\u2026"</string>
+    <string name="media_controller_live">ലൈവ്</string>
+    <string name="media_controller_playing">പ്ലേ ചെയ്യുന്നു</string>
+    <string name="media_controller_connecting">കണക്‌റ്റുചെയ്യുന്നു...</string>
+    <string name="bookmark_add">""ബുക്ക്‌മാർക്ക് ചേർക്കുക""</string>
+    <string name="bookmark_display">""ബുക്ക്‌മാർക്കുകൾ കാണിക്കുക""</string>
+    <string name="bookmark_empty">""ബുക്ക്മാർക്കുകൾ ഒന്നുമില്ല""</string>
+    <string name="bookmark_exist">"“ബുക്ക്മാർക്ക് ഇതിനകം നിലവിലുണ്ട്”"</string>
+    <string name="bookmark_add_success">"“ബുക്ക്മാർക്ക് ചേർത്തു”"</string>
+    <string name="bookmark_list">""ബുക്ക്മാർക്കുകൾ""</string>
+    <string name="bookmark_title">"തലക്കെട്ട്"</string>
+    <string name="bookmark_location">""ലൊക്കേഷൻ""</string>
+    <string name="delete_all">""എല്ലാം ഇല്ലാതാക്കുക""</string>
+    <string name="default_title">""സ്ഥിര പേര്""</string>
+    <string name="more_image">കൂടുതൽ ചിത്രങ്ങൾ</string>
+    <string name="mute_nosupport">നിശബ്ദമാക്കാൻ കഴിയില്ല: വീഡിയോ പിന്തുണയ്ക്കുന്നില്ല</string>
+    <string name="map_activity_not_found_err">സ്ഥാനം കാണിക്കുന്നതിന് മാപ്പ് അപ്ലിക്കേഷനുകള്‍ ഇന്‍സ്റ്റാള്‍ ചെയ്തിട്ടില്ല.</string>
+    <string name="fail_trim">ക്ഷമിക്കുക, ഈ വീഡിയോ ഫയൽ ട്രിം ചെയ്യാൻ കഴിയില്ല</string>
+    <string name="drm_license_info">DRM ലൈസൻസ് വിവരം</string>
+</resources>
diff --git a/res/values-mr/cm_strings.xml b/res/values-mr/cm_strings.xml
new file mode 100644
index 0000000..81a1e5e
--- /dev/null
+++ b/res/values-mr/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">वेळ रेकॉर्ड करा</string>
+</resources>
diff --git a/res/values-mr/codeaurora_strings.xml b/res/values-mr/codeaurora_strings.xml
new file mode 100644
index 0000000..0d413b4
--- /dev/null
+++ b/res/values-mr/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">पायरी</string>
+    <string name="step_option_desc">फास्ट फॉरवर्ड/रिवाईंड पायरी सानुकूल करा</string>
+    <string name="setp_option_three_second">3 सेकंद</string>
+    <string name="setp_option_six_second">6 सेकंद</string>
+    <string name="loop">""लूप""</string>
+    <string name="single">""एकल""</string>
+    <string name="stereo">""स्टिरिओ""</string>
+    <string name="speaker_on">स्पीकर चालू</string>
+    <string name="speaker_off">स्पीकर बंद</string>
+    <string name="speaker_need_headset">हे वैशिष्ट्य वापरण्यासाठी हेडफोन्स प्लग इन करा.</string>
+    <string name="single_track">""एक ट्रॅक""</string>
+    <string name="input_url">""URL लिहा""</string>
+    <string name="streaming_settings">""स्ट्रीमिंग सेटिंग्ज""</string>
+    <string name="next">""पुढील""</string>
+    <string name="previous">""मागील""</string>
+    <string name="buffer_size">बफर आकारमान</string>
+    <string name="apn">प्राधान्यीकृत APN</string>
+    <string name="rtp_min_port">किमान पोर्ट</string>
+    <string name="rtp_max_port">कमाल पोर्ट</string>
+    <string name="set_rtp_min_port">किमान पोर्ट सेट करा</string>
+    <string name="set_rtp_max_port">कमाल पोर्ट सेट करा</string>
+    <string name="set_buffer_size">बफर आकारमान सेट करा</string>
+    <string name="set_apn">प्राधान्यीकृत APN निवडा</string>
+    <string name="setting">सेटिंग्ज</string>
+    <string name="server_timeout_title">""सर्व्हरचा वेळ संपला""</string>
+    <string name="server_timeout_message">""व्हिडिओ प्ले करण्यासाठी सर्व्हरला रिकनेक्ट करायचा?""</string>
+    <string name="videoview_error_text_cannot_connect_retry">""कनेक्शन अपयशी झाले, सह कनेक्ट करण्याचा प्रयत्न करत आहे %1$d\u2026""</string>
+    <string name="media_controller_live">लाईव</string>
+    <string name="media_controller_playing">प्ले करत आहे</string>
+    <string name="media_controller_connecting">कनेक्ट करीत आहे...</string>
+    <string name="bookmark_add">""बुकमार्क जोडा""</string>
+    <string name="bookmark_display">""वाचनखुणा दर्शवा""</string>
+    <string name="bookmark_empty">""वाचनखुणा नाहीत""</string>
+    <string name="bookmark_exist">""वाचनखुण आधीच अस्तित्वात आहे""</string>
+    <string name="bookmark_add_success">""वाचनखुण जोडली""</string>
+    <string name="bookmark_list">""वाचनखुणा""</string>
+    <string name="bookmark_title">""शीर्षक""</string>
+    <string name="bookmark_location">""स्थान""</string>
+    <string name="delete_all">""सर्व हटवा""</string>
+    <string name="default_title">""डिफॉल्ट शीर्षक""</string>
+    <string name="more_image">अधिक प्रतिमा</string>
+    <string name="mute_nosupport">निःशब्द करू शकत नाही : व्हिडिओ समर्थित नाही</string>
+    <string name="map_activity_not_found_err">स्थान दाखवण्यासाठी नकाशे स्थापित केलेले नाहीत.</string>
+    <string name="fail_trim">क्षमस्व, ही व्हिडिओ फाइल ट्रिम करता येत नाही</string>
+    <string name="drm_license_info">DRM लायसन्स माहिती</string>
+</resources>
diff --git a/res/values-nb/cm_strings.xml b/res/values-nb/cm_strings.xml
new file mode 100644
index 0000000..838ceb9
--- /dev/null
+++ b/res/values-nb/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Opptakstid</string>
+</resources>
diff --git a/res/values-nb/codeaurora_strings.xml b/res/values-nb/codeaurora_strings.xml
new file mode 100644
index 0000000..4c797a7
--- /dev/null
+++ b/res/values-nb/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Steg</string>
+    <string name="step_option_desc">TIlpassing av spoling frem/tilbake</string>
+    <string name="setp_option_three_second">3 sekunder</string>
+    <string name="setp_option_six_second">6 sekunder</string>
+    <string name="loop">"Sløyfe"</string>
+    <string name="single">"Enkel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Høytaler PÅ</string>
+    <string name="speaker_off">Høytaler AV</string>
+    <string name="speaker_need_headset">Plugg i hodetelefoner for å bruke denne funksjonen.</string>
+    <string name="single_track">"Enkelt spor"</string>
+    <string name="input_url">"Angi URL-adressen"</string>
+    <string name="streaming_settings">"Streaming innstillinger"</string>
+    <string name="next">"Neste"</string>
+    <string name="previous">"Forrige"</string>
+    <string name="buffer_size">Buffer Størrelse</string>
+    <string name="apn">Foretrukket APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Angi min port</string>
+    <string name="set_rtp_max_port">Angi maks port</string>
+    <string name="set_buffer_size">Angi størrelse på hurtigbuffer</string>
+    <string name="set_apn">Velg foretrukket APN</string>
+    <string name="setting">Innstillinger</string>
+    <string name="server_timeout_title">"Tidsavbrudd for serveren"</string>
+    <string name="server_timeout_message">"Koble til serveren på nytt for å spille av videoen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Tilkoblingen mislyktes, prøver å koble til %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Spiller</string>
+    <string name="media_controller_connecting">Kobler til\u2026</string>
+    <string name="bookmark_add">"Legg til bokmerke"</string>
+    <string name="bookmark_display">"Vis bokmerker"</string>
+    <string name="bookmark_empty">"Ingen bokmerker"</string>
+    <string name="bookmark_exist">"Bokmerket finnes allerede"</string>
+    <string name="bookmark_add_success">"Bokmerke lagt til"</string>
+    <string name="bookmark_list">"Bokmerker"</string>
+    <string name="bookmark_title">"Tittel"</string>
+    <string name="bookmark_location">"Posisjon"</string>
+    <string name="delete_all">"Slett alle"</string>
+    <string name="default_title">"Standardtittel"</string>
+    <string name="more_image">Flere bilder</string>
+    <string name="mute_nosupport">Kan ikke slå av lyd: videoen støttes ikke</string>
+    <string name="map_activity_not_found_err">Det er ingen kart app installert for å vise plasseringen.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videoer</item>
+    </plurals>
+    <string name="cannot_share_items">Maksimalt 300 elementer til deling om gangen</string>
+    <string name="share_dialogue_title">Del via</string>
+    <string name="no_faces">Ingen ansikter</string>
+    <string name="fail_trim">Beklager, denne videofilen kan ikke trimmes</string>
+    <string name="can_not_trim">Bare MP4- og 3GP-filer kan trimmes</string>
+    <string name="drm_license_info">DRM lisensinfo</string>
+    <string name="timeline_title">Tidslinje</string>
+    <string name="albums_title">Album</string>
+    <string name="videos_title">Videoer</string>
+    <string name="action_viewtype_list">Listevisning</string>
+    <string name="tvEmptyAlbum">Fant ingen bilder</string>
+    <string name="tvEmptyVideos">Fant ingen videoer</string>
+    <string name="text_makeup_whiten">Blek</string>
+    <string name="text_makeup_Soften">Mykgjør</string>
+    <string name="text_makeup_trimface">Trimfjes</string>
+    <string name="text_makeup_bigeye">Storøye</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Tavle</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Fjern gjenskinn</string>
+    <string name="hazebuster_acts">Tåkefjerner</string>
+    <string name="seestraight_acts">Se rett</string>
+    <string name="seestraight_input_image_is_small">Angitt bilde er for lite til å behandles.</string>
+    <string name="seestraight_process_fail">Kunne ikke behandle bilde.</string>
+    <string name="trim_video_exit_title">Forkast endringer?</string>
+    <string name="trim_video_exit_msg">Forkast endringer gjort på denne videoen?</string>
+    <string name="trim_video_exit_discard">FORKAST</string>
+</resources>
diff --git a/res/values-nl/cm_strings.xml b/res/values-nl/cm_strings.xml
new file mode 100644
index 0000000..e5c79f9
--- /dev/null
+++ b/res/values-nl/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tijd van opname</string>
+</resources>
diff --git a/res/values-nl/codeaurora_strings.xml b/res/values-nl/codeaurora_strings.xml
new file mode 100644
index 0000000..10a9a64
--- /dev/null
+++ b/res/values-nl/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Stap</string>
+    <string name="step_option_desc">Stapgrootte vooruitspoelen/terugspoelen aanpassen</string>
+    <string name="setp_option_three_second">3 seconden</string>
+    <string name="setp_option_six_second">6 seconden</string>
+    <string name="loop">"Herhalen"</string>
+    <string name="single">"Enkel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Luidspreker AAN</string>
+    <string name="speaker_off">Luidspreker UIT</string>
+    <string name="speaker_need_headset">Sluit een koptelefoon aan om deze functie te gebruiken.</string>
+    <string name="single_track">"Enkel nummer"</string>
+    <string name="input_url">"URL invoeren"</string>
+    <string name="streaming_settings">"Instellingen voor streaming"</string>
+    <string name="next">"Volgende"</string>
+    <string name="previous">"Vorige"</string>
+    <string name="buffer_size">Buffergrootte</string>
+    <string name="apn">Voorkeurs-APN</string>
+    <string name="rtp_min_port">Min. poort</string>
+    <string name="rtp_max_port">Max. poort</string>
+    <string name="set_rtp_min_port">Minimale poort instellen</string>
+    <string name="set_rtp_max_port">Maximale poort instellen</string>
+    <string name="set_buffer_size">Buffergrootte instellen</string>
+    <string name="set_apn">Voorkeurs-APN selecteren</string>
+    <string name="setting">Instellingen</string>
+    <string name="server_timeout_title">"Time-out van de server"</string>
+    <string name="server_timeout_message">"Opnieuw verbinding maken met de server om de video af te spelen?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Verbinding mislukt, probeert opnieuw verbinding te maken met %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Afspelen</string>
+    <string name="media_controller_connecting">Verbinding maken\u2026</string>
+    <string name="bookmark_add">"Favoriet toevoegen"</string>
+    <string name="bookmark_display">"Favorieten weergeven"</string>
+    <string name="bookmark_empty">"Geen favorieten"</string>
+    <string name="bookmark_exist">"Favoriet bestaat al"</string>
+    <string name="bookmark_add_success">"Favoriet toegevoegd"</string>
+    <string name="bookmark_list">"Favorieten"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Locatie"</string>
+    <string name="delete_all">"Alles verwijderen"</string>
+    <string name="default_title">"Standaardtitel"</string>
+    <string name="more_image">Meer afbeeldingen</string>
+    <string name="mute_nosupport">Kan geluid niet dempen: video niet ondersteund</string>
+    <string name="map_activity_not_found_err">Er is geen kaartenapp geïnstalleerd om de locatie weer te geven.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video\'s</item>
+    </plurals>
+    <string name="cannot_share_items">Maximaal aantal items dat gedeeld kan worden is 300</string>
+    <string name="share_dialogue_title">Delen via</string>
+    <string name="no_faces">Geen gezichten</string>
+    <string name="fail_trim">Kan deze video niet bijsnijden</string>
+    <string name="can_not_trim">Alleen mp4- en 3gp-bestanden kunnen worden bijgesneden</string>
+    <string name="drm_license_info">DRM licentie-informatie</string>
+    <string name="timeline_title">Tijdlijn</string>
+    <string name="albums_title">Albums</string>
+    <string name="videos_title">Video\'s</string>
+    <string name="action_viewtype_list">Lijstweergave</string>
+    <string name="tvEmptyAlbum">Geen foto\'s gevonden</string>
+    <string name="tvEmptyVideos">Geen video\'s gevonden</string>
+    <string name="text_makeup_whiten">Witter</string>
+    <string name="text_makeup_Soften">Zachter</string>
+    <string name="text_makeup_trimface">Gezicht bijwerken</string>
+    <string name="text_makeup_bigeye">Grote ogen</string>
+    <string name="truescanner_normal">Normaal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Reflecties verwijderen</string>
+    <string name="hazebuster_acts">Waas verwijderen</string>
+    <string name="seestraight_acts">Rechtuit kijken</string>
+    <string name="seestraight_input_image_is_small">Afbeelding is te klein om te verwerken.</string>
+    <string name="seestraight_process_fail">Kan afbeelding niet verwerken.</string>
+    <string name="trim_video_exit_title">Wijzigingen verwerpen?</string>
+    <string name="trim_video_exit_msg">Wijzigingen aan deze video verwerpen?</string>
+    <string name="trim_video_exit_discard">VERWERPEN</string>
+</resources>
diff --git a/res/values-or/cm_strings.xml b/res/values-or/cm_strings.xml
new file mode 100644
index 0000000..5679b30
--- /dev/null
+++ b/res/values-or/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">ସମୟ ରେକର୍ଡ କରନ୍ତୁ</string>
+</resources>
diff --git a/res/values-or/codeaurora_strings.xml b/res/values-or/codeaurora_strings.xml
new file mode 100644
index 0000000..d299dca
--- /dev/null
+++ b/res/values-or/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ଷ୍ଟେପ୍‌</string>
+    <string name="step_option_desc">ଦ୍ରୁତ ଅଗ୍ରଗାମି/ରିୱିଣ୍ଡ ପର୍ଯ୍ୟାୟ କଷ୍ଟମାଇଜ୍‍ କରନ୍ତୁ</string>
+    <string name="setp_option_three_second">3 ସେକେଣ୍ଡ</string>
+    <string name="setp_option_six_second">6 ସେକେଣ୍ଡ</string>
+    <string name="loop">""ଲୁପ୍‌""</string>
+    <string name="single">""ଏକକ""</string>
+    <string name="stereo">""ଷ୍ଟେରିଓ""</string>
+    <string name="speaker_on">ସ୍ପିକର୍‍ ଅନ୍‍</string>
+    <string name="speaker_off">ସ୍ପିକର୍‍ ଅଫ୍</string>
+    <string name="speaker_need_headset">ଏହି ବୈଶିଷ୍ଟ୍ୟ ବ୍ୟବହାର କରିବା ପାଇଁ ହେଡଫୋନସ୍‍ ପ୍ଲଗ୍‍-ଇନ୍‍ କରନ୍ତୁ</string>
+    <string name="single_track">""ଏକକ ଟ୍ରାକ୍""</string>
+    <string name="input_url">""URL ପ୍ରବେଶ କରନ୍ତୁ""</string>
+    <string name="streaming_settings">""ଷ୍ଟ୍ରିମିଂ ସେଟିଂସ୍""</string>
+    <string name="next">""ପରବର୍ତ୍ତୀ""</string>
+    <string name="previous">""ପୂର୍ବବର୍ତ୍ତୀ""</string>
+    <string name="buffer_size">ବଫର୍‍ ଆକାର</string>
+    <string name="apn">ପ୍ରା୍ଧାନ୍ୟ ଦିଆଯାଇଥିବା APN</string>
+    <string name="rtp_min_port">ସର୍ବନିମ୍ନ ପୋର୍ଟ</string>
+    <string name="rtp_max_port">ସର୍ବାଧିକ ପୋର୍ଟ</string>
+    <string name="set_rtp_min_port">ସର୍ବନିମ୍ନ ପୋର୍ଟ ସେଟ୍‍ କ୍ରନ୍ତୁ</string>
+    <string name="set_rtp_max_port">ସର୍ବାଧିକ ପୋର୍ଟ  ସେଟ୍‍ କ୍ରନ୍ତୁ</string>
+    <string name="set_buffer_size">ବଫର୍‍ ଆକାର  ସେଟ୍‍ କ୍ରନ୍ତୁ</string>
+    <string name="set_apn">ପ୍ରାଧାନ୍ୟ ଦିଆଯାଇଥିବା APN ସେଟ୍‍ କ୍ରନ୍ତୁ</string>
+    <string name="setting">ସେଟିଂସ୍</string>
+    <string name="server_timeout_title">""ସର୍ଭର୍ ସମୟ ଶେଷ""</string>
+    <string name="server_timeout_message">""ଭିଡିଓ ଚଳାଇବା ପାଇଁ ସଭର୍‍ ସହିତ ପୁନଃସଂଯୋଗ କରିବେ କି?""</string>
+    <string name="videoview_error_text_cannot_connect_retry">""ସଂଯୋଗ ବିଫଳ ହୋଇଛି, %1$d ସହିତ ସଂଯୋଗ ପାଇଁ ପୁନଃଚେଷ୍ଟା କରାଯାଉଛି\u2026""</string>
+    <string name="media_controller_live">ଲାଇଭ୍‍</string>
+    <string name="media_controller_playing">ଚାଳନା କରାଯାଉଛି</string>
+    <string name="media_controller_connecting">ସଂଯୋଗ କରୁଛି\u2026</string>
+    <string name="bookmark_add">""ବୁକମାର୍କ ଯୋଡନ୍ତୁ""</string>
+    <string name="bookmark_display">""ବୁକମାର୍କଗୁଡିକ ଦେଖାଇବା""</string>
+    <string name="bookmark_empty">""ବୁକମାର୍କଗୁଡିକ ନାହିଁ""</string>
+    <string name="bookmark_exist">""ବୁକମାର୍କ ଆଗରୁ ବିଦ୍ୟମାନ ଅଛି""</string>
+    <string name="bookmark_add_success">""ବୁକମାର୍କ ଯୋଗ କରାଯାଇଛି""</string>
+    <string name="bookmark_list">""ବୁକମାର୍କଗୁଡିକ""</string>
+    <string name="bookmark_title">""ଟାଇଟଲ୍""</string>
+    <string name="bookmark_location">""ଅବସ୍ଥାନ""</string>
+    <string name="delete_all">""ସମସ୍ତ ବିଲୋପ କରନ୍ତୁ""</string>
+    <string name="default_title">""ଡିଫଲ୍ଟ ଟାଇଟଲ୍""</string>
+    <string name="more_image">ଅଧିକ ଚିତ୍ର</string>
+    <string name="mute_nosupport">ମ୍ୟୁଟ୍‍ କରିହେବ ନାହିଁ : ଭିଡିଓ ସମଥିତ ନୁହେଁ</string>
+    <string name="map_activity_not_found_err">ଅବସ୍ଥାନ ପ୍ରଦର୍ଶନ କରିବା ପାଇଁ କୌଣସି ମାନଚିତ୍ର ଆପ୍ଲିକେସନ୍‍ ସଂଥାପିତ ହୋଇନାହିଁ।</string>
+    <string name="fail_trim">ଷମା କରିବେ, ଭିଡିଓ ଫାଇଲ୍‍ ଛୋଟ କରାଯାଇପାରିବ ନାହିଁ</string>
+    <string name="drm_license_info">DRM ଲାଇସେନ୍ସ ସୂଚନା</string>
+</resources>
diff --git a/res/values-pl/cm_strings.xml b/res/values-pl/cm_strings.xml
new file mode 100644
index 0000000..434b2f7
--- /dev/null
+++ b/res/values-pl/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Czas nagrania</string>
+</resources>
diff --git a/res/values-pl/codeaurora_strings.xml b/res/values-pl/codeaurora_strings.xml
new file mode 100644
index 0000000..5a33ef4
--- /dev/null
+++ b/res/values-pl/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Krok</string>
+    <string name="step_option_desc">Dostosuj stopnie przewijania/cofania</string>
+    <string name="setp_option_three_second">3 sekundy</string>
+    <string name="setp_option_six_second">6 sekund</string>
+    <string name="loop">"Pętla"</string>
+    <string name="single">"Pojedynczy"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Głośnik włączony</string>
+    <string name="speaker_off">Głośnik wyłączony</string>
+    <string name="speaker_need_headset">Podłącz słuchawki, aby skorzystać z tej funkcji.</string>
+    <string name="single_track">"Pojedynczy utwór"</string>
+    <string name="input_url">"Wprowadź adres URL"</string>
+    <string name="streaming_settings">"Ustawienia strumieniowania"</string>
+    <string name="next">"Następny"</string>
+    <string name="previous">"Poprzedni"</string>
+    <string name="buffer_size">Rozmiar bufora</string>
+    <string name="apn">Preferowany APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Ustaw min port</string>
+    <string name="set_rtp_max_port">Ustaw max port</string>
+    <string name="set_buffer_size">Ustaw rozmiar bufora</string>
+    <string name="set_apn">Wybierz preferowany APN</string>
+    <string name="setting">Ustawienia</string>
+    <string name="server_timeout_title">"Limit czasu serwera"</string>
+    <string name="server_timeout_message">"Połączyć ponownie się z serwerem, aby odtworzyć wideo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Połączenie nie powiodło się, próba odnowienia połączenia do %1$d\u2026"</string>
+    <string name="media_controller_live">Na żywo</string>
+    <string name="media_controller_playing">Odtwarzanie</string>
+    <string name="media_controller_connecting">Łączenie\u2026</string>
+    <string name="bookmark_add">"Dodaj zakładkę"</string>
+    <string name="bookmark_display">"Pokaż zakładki"</string>
+    <string name="bookmark_empty">"Brak zakładek"</string>
+    <string name="bookmark_exist">"Zakładka już istnieje"</string>
+    <string name="bookmark_add_success">"Dodano zakładkę"</string>
+    <string name="bookmark_list">"Zakładki"</string>
+    <string name="bookmark_title">"Tytuł"</string>
+    <string name="bookmark_location">"Lokalizacja"</string>
+    <string name="delete_all">"Usuń wszystkie"</string>
+    <string name="default_title">"Domyślny tytuł"</string>
+    <string name="more_image">Więcej zdjęć</string>
+    <string name="mute_nosupport">Nie można wyciszyć: film nieobsługiwany</string>
+    <string name="map_activity_not_found_err">Nie ma aplikacji mapy zainstalowanej, aby zobaczyć lokalizację.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d film</item>
+        <item quantity="few">%1$d filmy</item>
+        <item quantity="many">%1$d filmów</item>
+        <item quantity="other">%1$d filmów</item>
+    </plurals>
+    <string name="cannot_share_items">Maksymalnie możesz udostępnić 300 elementów</string>
+    <string name="share_dialogue_title">Udostępnij przez</string>
+    <string name="no_faces">Bez wykrytej twarzy</string>
+    <string name="fail_trim">Niestety, ten plik wideo nie może zostać przycięty</string>
+    <string name="can_not_trim">Tylko pliki mp4 i 3gp mogą zostać przycięte</string>
+    <string name="drm_license_info">Informacje o licencji DRM</string>
+    <string name="timeline_title">Oś czasu</string>
+    <string name="albums_title">Albumy</string>
+    <string name="videos_title">Filmy</string>
+    <string name="action_viewtype_list">Widok listy</string>
+    <string name="tvEmptyAlbum">Nie znaleziono zdjęć</string>
+    <string name="tvEmptyVideos">Nie znaleziono filmów</string>
+    <string name="text_makeup_whiten">Wybiel</string>
+    <string name="text_makeup_Soften">Zmiękczenie</string>
+    <string name="text_makeup_trimface">Przycinanie twarzy</string>
+    <string name="text_makeup_bigeye">Duże oko</string>
+    <string name="truescanner_normal">Normalny</string>
+    <string name="truescanner_white">Biała tablica</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Usuń odblask</string>
+    <string name="hazebuster_acts">Zredukuj efekt mgły</string>
+    <string name="seestraight_acts">Patrz prosto</string>
+    <string name="seestraight_input_image_is_small">Obraz wejściowy jest zbyt mały do przetworzenia.</string>
+    <string name="seestraight_process_fail">Nie udało się przetworzyć obrazu.</string>
+    <string name="trim_video_exit_title">Odrzucić zmiany?</string>
+    <string name="trim_video_exit_msg">Odrzucić zmiany wprowadzone do tego filmu?</string>
+    <string name="trim_video_exit_discard">ODRZUĆ</string>
+</resources>
diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
index 46871c6..319b0a6 100644
--- a/res/values-port/styles.xml
+++ b/res/values-port/styles.xml
@@ -37,15 +37,15 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">@color/popup_title_color</item>
-        <item name="android:layout_marginLeft">10dp</item>
+        <item name="android:layout_marginStart">10dp</item>
     </style>
     <style name="ViewfinderLabelLayout">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_marginTop">13dp</item>
         <item name="android:layout_marginBottom">@dimen/indicator_bar_width</item>
-        <item name="android:layout_marginLeft">13dp</item>
-        <item name="android:layout_marginRight">13dp</item>
+        <item name="android:layout_marginStart">13dp</item>
+        <item name="android:layout_marginEnd">13dp</item>
     </style>
     <style name="PanoViewHorizontalBar">
         <item name="android:background">#000000</item>
diff --git a/res/values-pt-rBR/cm_strings.xml b/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 0000000..7d929e3
--- /dev/null
+++ b/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tempo de gravação</string>
+</resources>
diff --git a/res/values-pt-rBR/codeaurora_strings.xml b/res/values-pt-rBR/codeaurora_strings.xml
new file mode 100644
index 0000000..05b4ba8
--- /dev/null
+++ b/res/values-pt-rBR/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Passo</string>
+    <string name="step_option_desc">Personalizar o avanço/retrocesso rápido</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Repetir"</string>
+    <string name="single">"Único"</string>
+    <string name="stereo">"Estéreo"</string>
+    <string name="speaker_on">Alto-falante ligado</string>
+    <string name="speaker_off">Alto-falante desligado</string>
+    <string name="speaker_need_headset">Conecte fones de ouvido para usar este recurso.</string>
+    <string name="single_track">"Faixa única"</string>
+    <string name="input_url">"Digite a URL"</string>
+    <string name="streaming_settings">"Configurações de streaming"</string>
+    <string name="next">"Próximo"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamanho do buffer</string>
+    <string name="apn">APN preferencial</string>
+    <string name="rtp_min_port">Porta mínima</string>
+    <string name="rtp_max_port">Porta máxima</string>
+    <string name="set_rtp_min_port">Definir a porta mínima</string>
+    <string name="set_rtp_max_port">Definir a porta máxima</string>
+    <string name="set_buffer_size">Definir o tamanho do buffer</string>
+    <string name="set_apn">Selecione a APN preferida</string>
+    <string name="setting">Configurações</string>
+    <string name="server_timeout_title">"Tempo de espera do servidor"</string>
+    <string name="server_timeout_message">"Reconectar ao servidor para tocar o vídeo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Falha na conexão, tentando reconectar ao %1$d\u2026"</string>
+    <string name="media_controller_live">Ao vivo</string>
+    <string name="media_controller_playing">Tocando</string>
+    <string name="media_controller_connecting">Conectando\u2026</string>
+    <string name="bookmark_add">"Adicionar favorito"</string>
+    <string name="bookmark_display">"Visualizar favoritos"</string>
+    <string name="bookmark_empty">"Não há favoritos"</string>
+    <string name="bookmark_exist">"O favorito já existe"</string>
+    <string name="bookmark_add_success">"Favorito adicionado"</string>
+    <string name="bookmark_list">"Favoritos"</string>
+    <string name="bookmark_title">"Título"</string>
+    <string name="bookmark_location">"Localização"</string>
+    <string name="delete_all">"Apagar tudo"</string>
+    <string name="default_title">"Título padrão"</string>
+    <string name="more_image">Mais imagens</string>
+    <string name="mute_nosupport">Impossivel silenciar: vídeo não compatível</string>
+    <string name="map_activity_not_found_err">Não há aplicativo de mapas instalado para mostrar o local.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vídeo</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">O número máximo de itens selecionados é 300</string>
+    <string name="share_dialogue_title">Compartilhar via</string>
+    <string name="no_faces">Sem rostos</string>
+    <string name="fail_trim">Desculpe, o arquivo de vídeo não pode ser cortado</string>
+    <string name="can_not_trim">Apenas arquivos mp4 e 3gp podem ser cortados</string>
+    <string name="drm_license_info">Informação de licença DRM</string>
+    <string name="timeline_title">Linha do tempo</string>
+    <string name="albums_title">Álbuns</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Visualização em lista</string>
+    <string name="tvEmptyAlbum">Nenhuma foto encontrada</string>
+    <string name="tvEmptyVideos">Nenhum vídeo encontrado</string>
+    <string name="text_makeup_whiten">Branquear</string>
+    <string name="text_makeup_Soften">Suavizar</string>
+    <string name="text_makeup_trimface">Melhorar rosto</string>
+    <string name="text_makeup_bigeye">Olhos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Quadro branco</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remover brilho</string>
+    <string name="hazebuster_acts">Ajuste de neblina</string>
+    <string name="seestraight_acts">Ver em linha reta</string>
+    <string name="seestraight_input_image_is_small">A imagem é pequena demais para processar.</string>
+    <string name="seestraight_process_fail">Não foi possível processar a imagem.</string>
+    <string name="trim_video_exit_title">Descartar as alterações?</string>
+    <string name="trim_video_exit_msg">Descartar as alterações feitas neste vídeo?</string>
+    <string name="trim_video_exit_discard">DESCARTAR</string>
+</resources>
diff --git a/res/values-pt-rPT/cm_strings.xml b/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 0000000..7d929e3
--- /dev/null
+++ b/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Tempo de gravação</string>
+</resources>
diff --git a/res/values-pt-rPT/codeaurora_strings.xml b/res/values-pt-rPT/codeaurora_strings.xml
new file mode 100644
index 0000000..421a927
--- /dev/null
+++ b/res/values-pt-rPT/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Intervalo</string>
+    <string name="step_option_desc">Personalizar o avanço/retrocesso rápido</string>
+    <string name="setp_option_three_second">3 segundos</string>
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="loop">"Repetir"</string>
+    <string name="single">"Simples"</string>
+    <string name="stereo">"Estéreo"</string>
+    <string name="speaker_on">Altifalante ligado</string>
+    <string name="speaker_off">Altifalante desligado</string>
+    <string name="speaker_need_headset">Ligue os auscultadores para usar esta funcionalidade.</string>
+    <string name="single_track">"Faixa única"</string>
+    <string name="input_url">"Insira a URL"</string>
+    <string name="streaming_settings">"Definições de transmissão"</string>
+    <string name="next">"Próximo"</string>
+    <string name="previous">"Anterior"</string>
+    <string name="buffer_size">Tamanho do buffer</string>
+    <string name="apn">APN preferida</string>
+    <string name="rtp_min_port">Porta mínima</string>
+    <string name="rtp_max_port">Porta máxima</string>
+    <string name="set_rtp_min_port">Definir a porta mínima</string>
+    <string name="set_rtp_max_port">Definir a porta máxima</string>
+    <string name="set_buffer_size">Definir o tamanho do buffer</string>
+    <string name="set_apn">Selecionar a APN preferida</string>
+    <string name="setting">Definições</string>
+    <string name="server_timeout_title">"Tempo de espera do servidor"</string>
+    <string name="server_timeout_message">"Reconectar ao servidor para reproduzir o vídeo?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Falha na ligação. A tentar reconectar-se a %1$d\u2026"</string>
+    <string name="media_controller_live">Ao vivo</string>
+    <string name="media_controller_playing">A reproduzir</string>
+    <string name="media_controller_connecting">A ligar\u2026</string>
+    <string name="bookmark_add">"Adicionar favorito"</string>
+    <string name="bookmark_display">"Visualizar favoritos"</string>
+    <string name="bookmark_empty">"Sem favoritos"</string>
+    <string name="bookmark_exist">"O favorito já existe"</string>
+    <string name="bookmark_add_success">"Favorito adicionado"</string>
+    <string name="bookmark_list">"Favoritos"</string>
+    <string name="bookmark_title">"Título"</string>
+    <string name="bookmark_location">"Localização"</string>
+    <string name="delete_all">"Apagar tudo"</string>
+    <string name="default_title">"Título padrão"</string>
+    <string name="more_image">Mais imagens</string>
+    <string name="mute_nosupport">Não pode silenciar: vídeo não suportado</string>
+    <string name="map_activity_not_found_err">Não há nenhuma aplicaçação de mapas instalada para mostrar o local.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d vídeo</item>
+        <item quantity="other">%1$d vídeos</item>
+    </plurals>
+    <string name="cannot_share_items">O número máximo de itens selecionados é 300</string>
+    <string name="share_dialogue_title">Partilhar através de</string>
+    <string name="no_faces">Sem rostos</string>
+    <string name="fail_trim">Desculpe, mas este vídeo não pode ser cortado</string>
+    <string name="can_not_trim">Só ficheiros em mp4 ou 3gp podem ser cortados</string>
+    <string name="drm_license_info">Informação da licença DRM</string>
+    <string name="timeline_title">Cronologia</string>
+    <string name="albums_title">Álbuns</string>
+    <string name="videos_title">Vídeos</string>
+    <string name="action_viewtype_list">Vista de lista</string>
+    <string name="tvEmptyAlbum">Não foram encontradas fotos</string>
+    <string name="tvEmptyVideos">Não foram encontrados vídeos</string>
+    <string name="text_makeup_whiten">Branquear</string>
+    <string name="text_makeup_Soften">Amaciar</string>
+    <string name="text_makeup_trimface">Melhorar rosto</string>
+    <string name="text_makeup_bigeye">Olhos grandes</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Quadro branco</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remover o brilho</string>
+    <string name="hazebuster_acts">Ajuste de neblina</string>
+    <string name="seestraight_acts">Melhor visualização</string>
+    <string name="seestraight_input_image_is_small">A imagem é demasiado pequena para processar.</string>
+    <string name="seestraight_process_fail">Não foi possível processar a imagem.</string>
+    <string name="trim_video_exit_title">Rejeitar alterações?</string>
+    <string name="trim_video_exit_msg">Rejeitar as alterações feitas a este vídeo?</string>
+    <string name="trim_video_exit_discard">REJEITAR</string>
+</resources>
diff --git a/res/values-ro/cm_strings.xml b/res/values-ro/cm_strings.xml
new file mode 100644
index 0000000..2a64b42
--- /dev/null
+++ b/res/values-ro/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Dată înregistrare</string>
+</resources>
diff --git a/res/values-ro/codeaurora_strings.xml b/res/values-ro/codeaurora_strings.xml
new file mode 100644
index 0000000..02f9379
--- /dev/null
+++ b/res/values-ro/codeaurora_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Pas</string>
+    <string name="step_option_desc">Personalizează pasul derulării/înaintării rapide</string>
+    <string name="setp_option_three_second">3 secunde</string>
+    <string name="setp_option_six_second">6 secunde</string>
+    <string name="loop">"Buclă"</string>
+    <string name="single">"Singur"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Difuzor pornit</string>
+    <string name="speaker_off">Difuzor oprit</string>
+    <string name="speaker_need_headset">Conectați căștile pentru a utiliza această caracteristică.</string>
+    <string name="single_track">"Linie singulară"</string>
+    <string name="input_url">"Introduceți URL-ul"</string>
+    <string name="streaming_settings">"Setările de streaming"</string>
+    <string name="next">"Următoarea"</string>
+    <string name="previous">"Înapoi"</string>
+    <string name="buffer_size">Dimensiune tampon</string>
+    <string name="apn">APN preferat</string>
+    <string name="rtp_min_port">Port minim</string>
+    <string name="rtp_max_port">Port maxim</string>
+    <string name="set_rtp_min_port">Setează portul minim</string>
+    <string name="set_rtp_max_port">Setează portul maxim</string>
+    <string name="set_buffer_size">Setează dimensiune tampon</string>
+    <string name="set_apn">Selectați APN preferat</string>
+    <string name="setting">Setări</string>
+    <string name="server_timeout_title">"Expirare server"</string>
+    <string name="server_timeout_message">"Reconectați la server pentru a reda video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Conexiunea a eșuat, se încearcă reconectarea la %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Redând</string>
+    <string name="media_controller_connecting">Se conectează\u2026</string>
+    <string name="bookmark_add">"Adaugă semn de carte"</string>
+    <string name="bookmark_display">"Arată semne de carte"</string>
+    <string name="bookmark_empty">"Fără semne de carte"</string>
+    <string name="bookmark_exist">"Semnul de carte există deja"</string>
+    <string name="bookmark_add_success">"Semn de carte adăugat"</string>
+    <string name="bookmark_list">"Semne de carte"</string>
+    <string name="bookmark_title">"Titlu"</string>
+    <string name="bookmark_location">"Locație"</string>
+    <string name="delete_all">"Șterge toate"</string>
+    <string name="default_title">"Titlul implicit"</string>
+    <string name="more_image">Mai multe imagini</string>
+    <string name="mute_nosupport">Nu puteți dezactiva volumul: videoul nu este acceptat</string>
+    <string name="map_activity_not_found_err">Nu există nicio aplicație cu hărți instalată care să arate locația.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d videoclip</item>
+        <item quantity="few">%1$d (de) videoclipuri</item>
+        <item quantity="other">%1$d (de) videoclipuri</item>
+    </plurals>
+    <string name="cannot_share_items">Numărul maxim de elemente selectate pentru împărtășire este de 300 de elemente</string>
+    <string name="share_dialogue_title">Distribuiți prin</string>
+    <string name="no_faces">Nicio față</string>
+    <string name="fail_trim">Ne pare rău, acest fișier video nu poate fi tăiat</string>
+    <string name="can_not_trim">Numai fişierele mp4 şi 3gp pot fi tăiate</string>
+    <string name="drm_license_info">Informații licență DRM</string>
+    <string name="timeline_title">Cronologie</string>
+    <string name="albums_title">Albume</string>
+    <string name="videos_title">Videoclipuri</string>
+    <string name="action_viewtype_list">Vedere listă</string>
+    <string name="tvEmptyAlbum">Nu s-au găsit poze</string>
+    <string name="tvEmptyVideos">Nu s-au găsit videoclipuri</string>
+    <string name="text_makeup_whiten">Albire</string>
+    <string name="text_makeup_Soften">Înmuiere</string>
+    <string name="text_makeup_trimface">Tăiere față</string>
+    <string name="text_makeup_bigeye">Ochi mari</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Placă-albă</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Eliminare Orbire</string>
+    <string name="hazebuster_acts">Distrugător de Ceață</string>
+    <string name="seestraight_acts">Vedere Dreaptă</string>
+    <string name="seestraight_input_image_is_small">Imaginea de intrare este prea mică pentru a fi procesată.</string>
+    <string name="seestraight_process_fail">Nu s-a putut procesa imaginea.</string>
+    <string name="trim_video_exit_title">Renunțați la modificări?</string>
+    <string name="trim_video_exit_msg">Renunțați la modificările făcute la acest videoclip?</string>
+    <string name="trim_video_exit_discard">RENUNȚARE</string>
+</resources>
diff --git a/res/values-ru/cm_strings.xml b/res/values-ru/cm_strings.xml
new file mode 100644
index 0000000..0cf9715
--- /dev/null
+++ b/res/values-ru/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Время записи</string>
+</resources>
diff --git a/res/values-ru/codeaurora_strings.xml b/res/values-ru/codeaurora_strings.xml
new file mode 100644
index 0000000..975d572
--- /dev/null
+++ b/res/values-ru/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Шаг перемотки</string>
+    <string name="step_option_desc">Настройка интервала для быстрой перемотки вперед или назад</string>
+    <string name="setp_option_three_second">3 секунды</string>
+    <string name="setp_option_six_second">6 секунд</string>
+    <string name="loop">"Зациклить"</string>
+    <string name="single">"Однократно"</string>
+    <string name="stereo">"Стерео"</string>
+    <string name="speaker_on">Вкл. динамик</string>
+    <string name="speaker_off">Выкл. динамик</string>
+    <string name="speaker_need_headset">Подключите наушники для использования этой функции.</string>
+    <string name="single_track">"Один трек"</string>
+    <string name="input_url">"Введите URL"</string>
+    <string name="streaming_settings">"Потоковая передача"</string>
+    <string name="next">"След."</string>
+    <string name="previous">"Пред."</string>
+    <string name="buffer_size">Размер буфера передачи</string>
+    <string name="apn">Точка доступа по умолчанию</string>
+    <string name="rtp_min_port">Минимальный порт</string>
+    <string name="rtp_max_port">Максимальный порт</string>
+    <string name="set_rtp_min_port">Установка мин. номера порта</string>
+    <string name="set_rtp_max_port">Установка макс. номера порта</string>
+    <string name="set_buffer_size">Установка размера буфера передачи</string>
+    <string name="set_apn">Предпочтительная точка доступа</string>
+    <string name="setting">Настройки</string>
+    <string name="server_timeout_title">"Время ожидания сервера"</string>
+    <string name="server_timeout_message">"Переподключиться к серверу для воспроизведения видеофайла?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Сбой связи. Повторное подключение к %1$d\u2026"</string>
+    <string name="media_controller_live">Прямой эфир</string>
+    <string name="media_controller_playing">Воспроизведение</string>
+    <string name="media_controller_connecting">Подключение\u2026</string>
+    <string name="bookmark_add">"Добавить закладку"</string>
+    <string name="bookmark_display">"Показать закладки"</string>
+    <string name="bookmark_empty">"Нет закладок"</string>
+    <string name="bookmark_exist">"Закладка уже создана"</string>
+    <string name="bookmark_add_success">"Закладка добавлена"</string>
+    <string name="bookmark_list">"Закладки"</string>
+    <string name="bookmark_title">"Название"</string>
+    <string name="bookmark_location">"Местоположение"</string>
+    <string name="delete_all">"Удалить все"</string>
+    <string name="default_title">"Заголовок по умолчанию"</string>
+    <string name="more_image">Другие изображения</string>
+    <string name="mute_nosupport">Невозможно отключить звук: видеофайл не поддерживается</string>
+    <string name="map_activity_not_found_err">Приложение для работы с картами не установлено. Показ местоположения невозможен.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d видео</item>
+        <item quantity="few">%1$d видео</item>
+        <item quantity="many">%1$d видео</item>
+        <item quantity="other">%1$d видео</item>
+    </plurals>
+    <string name="cannot_share_items">Максимальное количество выбранных элементов для передачи 300</string>
+    <string name="share_dialogue_title">Способ отправки</string>
+    <string name="no_faces">Без лиц</string>
+    <string name="fail_trim">Этот видеофайл невозможно обрезать</string>
+    <string name="can_not_trim">Можно обрезать только файлы в форматах MP4 и 3GP</string>
+    <string name="drm_license_info">Сведения о лицензии DRM</string>
+    <string name="timeline_title">Хронология</string>
+    <string name="albums_title">Альбомы</string>
+    <string name="videos_title">Видео</string>
+    <string name="action_viewtype_list">Список</string>
+    <string name="tvEmptyAlbum">Нет фотографий</string>
+    <string name="tvEmptyVideos">Нет видео</string>
+    <string name="text_makeup_whiten">Осветление</string>
+    <string name="text_makeup_Soften">Смягчение</string>
+    <string name="text_makeup_trimface">Обрезать по овалу лица</string>
+    <string name="text_makeup_bigeye">Увеличить глаза</string>
+    <string name="truescanner_normal">Нормальный</string>
+    <string name="truescanner_white">Доска</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Удалить блики</string>
+    <string name="hazebuster_acts">Удалить дымку</string>
+    <string name="seestraight_acts">Смотрите прямо</string>
+    <string name="seestraight_input_image_is_small">Исходное изображение слишком мало для обработки.</string>
+    <string name="seestraight_process_fail">Не удалось обработать изображение.</string>
+    <string name="trim_video_exit_title">Отменить изменения?</string>
+    <string name="trim_video_exit_msg">Отменить изменения, внесенные в это видео?</string>
+    <string name="trim_video_exit_discard">ОТМЕНИТЬ</string>
+</resources>
diff --git a/res/values-sc-rIT/codeaurora_strings.xml b/res/values-sc-rIT/codeaurora_strings.xml
new file mode 100644
index 0000000..f9673a0
--- /dev/null
+++ b/res/values-sc-rIT/codeaurora_strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_six_second">6 segundos</string>
+    <string name="setting">Cunfiguratziones</string>
+    <string name="server_timeout_title">"Tempus de isetu pro su server acabbadu"</string>
+    <string name="bookmark_title">"Tìtulu"</string>
+    <string name="bookmark_location">"Positzione"</string>
+    <string name="delete_all">"Iscantzella totu"</string>
+    <string name="videos_title">Vìdeos</string>
+    <string name="trim_video_exit_title">Non cheres sarvare sas modìficas?</string>
+</resources>
diff --git a/res/values-si/cm_strings.xml b/res/values-si/cm_strings.xml
new file mode 100644
index 0000000..b84b1f9
--- /dev/null
+++ b/res/values-si/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">රෙකෝඩිත වේලාව</string>
+</resources>
diff --git a/res/values-si/codeaurora_strings.xml b/res/values-si/codeaurora_strings.xml
new file mode 100644
index 0000000..330459d
--- /dev/null
+++ b/res/values-si/codeaurora_strings.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="step_option_desc">ශීඝ්‍රව ඉදිරියට/පසුධාවන පියවර රිසිකරණය</string>
+    <string name="loop">"ලූපය"</string>
+    <string name="single">"තනිකඩ"</string>
+    <string name="stereo">"ත්‍රිමාන"</string>
+    <string name="speaker_on">ස්පීකරය සක්‍රීයයි</string>
+    <string name="speaker_off">ස්පීකරය අක්‍රීයයි</string>
+    <string name="speaker_need_headset">මෙම විශේෂාංගය භාවිතයට ඉස් බණුව පේනුගත කරන්න.</string>
+    <string name="single_track">"තනි ඛණ්ඩය"</string>
+    <string name="input_url">"URL ඇතුළත් කරන්න"</string>
+    <string name="streaming_settings">"ප්‍රවාහන සැකසීම්"</string>
+    <string name="next">"ඊළඟ"</string>
+    <string name="previous">"පෙර"</string>
+    <string name="buffer_size">බෆර ප්‍රමාණය</string>
+    <string name="apn">වඩා ලැදි APN ය</string>
+    <string name="rtp_min_port">අවම තොට</string>
+    <string name="rtp_max_port">උපරිම තොට</string>
+    <string name="set_rtp_min_port">අවම තොට සකසන්න</string>
+    <string name="set_rtp_max_port">උපරිම තොට සකසන්න</string>
+    <string name="set_buffer_size">බෆර ප්‍රමාණය සකසන්න</string>
+    <string name="set_apn">වඩා ලැදි APN ය තෝරන්න</string>
+    <string name="setting">සැකසීම්</string>
+    <string name="server_timeout_title">"සේවාදායකය කල්ඉකුත් විය"</string>
+    <string name="server_timeout_message">"වීඩියෝව ධාවනය සඳහා සේවාදායකයට යලි සම්බන්ධ වන්නද?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"සම්බන්ධය අසමත්විය, %1$d වෙත යලි සම්බන්ධවීමට උත්සාහ කරමින්\u2026"</string>
+    <string name="media_controller_live">සජීවී</string>
+    <string name="media_controller_playing">ධාවනය කරමින්</string>
+    <string name="media_controller_connecting">සම්බන්ධ වෙමින්\u2026</string>
+    <string name="bookmark_add">"පොත් යොමුවක් එක් කරන්න"</string>
+    <string name="bookmark_display">"පොත් යොමු පෙන්වන්න"</string>
+    <string name="bookmark_empty">"පොත් යොමු නැත"</string>
+    <string name="bookmark_exist">"පොත් යොමුව දැනටමත් පවතී"</string>
+    <string name="bookmark_add_success">"පොත් යොමුව එක් කෙරුණි"</string>
+    <string name="bookmark_list">"පොත් යොමු"</string>
+    <string name="bookmark_title">"පටබැඳිනාමය"</string>
+    <string name="bookmark_location">"ස්ථානය"</string>
+    <string name="delete_all">"සියල්ල මකන්න"</string>
+    <string name="default_title">"පෙරනිමි පටබැඳිනාමය"</string>
+    <string name="mute_nosupport">නිශ්ශබ්ද කල නොහැක : සහාය නොදක්වන වීඩියෝවකි</string>
+    <string name="fail_trim">කනගාටුයි, මෙම වීඩියෝ ගොනුව කොට කල නොහැක</string>
+</resources>
diff --git a/res/values-sk/cm_strings.xml b/res/values-sk/cm_strings.xml
new file mode 100644
index 0000000..74f7a27
--- /dev/null
+++ b/res/values-sk/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Čas nahrania</string>
+</resources>
diff --git a/res/values-sk/codeaurora_strings.xml b/res/values-sk/codeaurora_strings.xml
new file mode 100644
index 0000000..ac7e1c2
--- /dev/null
+++ b/res/values-sk/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Krok</string>
+    <string name="step_option_desc">Prispôsobiť krok rýchleho pretočenia dopredu/dozadu</string>
+    <string name="setp_option_three_second">3 sekundy</string>
+    <string name="setp_option_six_second">6 sekúnd</string>
+    <string name="loop">"Opakovanie"</string>
+    <string name="single">"Jednoduchý"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Zapnúť reproduktor</string>
+    <string name="speaker_off">Vypnúť reproduktor</string>
+    <string name="speaker_need_headset">Pripojte slúchadlá pre použitie tejto funkcie.</string>
+    <string name="single_track">"Jedna stopa"</string>
+    <string name="input_url">"Zadať adresu URL"</string>
+    <string name="streaming_settings">"Nastavenia streamovania"</string>
+    <string name="next">"Ďalšie"</string>
+    <string name="previous">"Predchádzajúce"</string>
+    <string name="buffer_size">Veľkosť vyrovnávacej pamäte</string>
+    <string name="apn">Uprednostňovaný prístupový bod</string>
+    <string name="rtp_min_port">Minimálny port</string>
+    <string name="rtp_max_port">Maximálny port</string>
+    <string name="set_rtp_min_port">Nastaviť minimálny port</string>
+    <string name="set_rtp_max_port">Nastaviť maximálny port</string>
+    <string name="set_buffer_size">Nastaviť veľkosť vyrovnávacej pamäte</string>
+    <string name="set_apn">Vybrať uprednostňovaný prístupový bod</string>
+    <string name="setting">Nastavenia</string>
+    <string name="server_timeout_title">"Časový limit servera"</string>
+    <string name="server_timeout_message">"Pripojiť sa znova k serveru pre prehrávanie videa?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Pripojenie zlyhalo, pokúšanie sa o opätovné pripojenie k %1$d\u2026"</string>
+    <string name="media_controller_live">Naživo</string>
+    <string name="media_controller_playing">Prehrávanie</string>
+    <string name="media_controller_connecting">Pripájanie\u2026</string>
+    <string name="bookmark_add">"Pridať záložku"</string>
+    <string name="bookmark_display">"Zobraziť záložky"</string>
+    <string name="bookmark_empty">"Žiadne záložky"</string>
+    <string name="bookmark_exist">"Záložka už existuje"</string>
+    <string name="bookmark_add_success">"Záložka bola pridaná"</string>
+    <string name="bookmark_list">"Záložky"</string>
+    <string name="bookmark_title">"Názov"</string>
+    <string name="bookmark_location">"Poloha"</string>
+    <string name="delete_all">"Vymazať všetky"</string>
+    <string name="default_title">"Predvolený názov"</string>
+    <string name="more_image">Viac obrázkov</string>
+    <string name="mute_nosupport">Nie je možné stíšiť: video nie je podporované</string>
+    <string name="map_activity_not_found_err">Nie je nainštalovaná žiadna mapová aplikácia pre zobrazenie polohy.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="few">%1$d videá</item>
+        <item quantity="many">%1$d videí</item>
+        <item quantity="other">%1$d videí</item>
+    </plurals>
+    <string name="cannot_share_items">Max. počet vybraných položiek pre zdieľanie je 300</string>
+    <string name="share_dialogue_title">Zdieľať cez</string>
+    <string name="no_faces">Žiadne tváre</string>
+    <string name="fail_trim">Prepáčte, ale toto video nie je možné orezať</string>
+    <string name="can_not_trim">Orezať je možné iba súbory mp4 a 3gp</string>
+    <string name="drm_license_info">Informácie o licencii DRM</string>
+    <string name="timeline_title">Časová os</string>
+    <string name="albums_title">Albumy</string>
+    <string name="videos_title">Videá</string>
+    <string name="action_viewtype_list">Zobrazenie zoznamu</string>
+    <string name="tvEmptyAlbum">Žiadne fotografie</string>
+    <string name="tvEmptyVideos">Žiadne videá</string>
+    <string name="text_makeup_whiten">Bielenie</string>
+    <string name="text_makeup_Soften">Zmäkčenie</string>
+    <string name="text_makeup_trimface">Orezanie tváre</string>
+    <string name="text_makeup_bigeye">Veľké oči</string>
+    <string name="truescanner_normal">Normálne</string>
+    <string name="truescanner_white">Biela tabuľa</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Odstránenie odleskov</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">Pohľad priamo</string>
+    <string name="seestraight_input_image_is_small">Vstupný obraz je príliš malý na spracovanie.</string>
+    <string name="seestraight_process_fail">Obrázok sa nepodarilo spracovať.</string>
+    <string name="trim_video_exit_title">Zrušiť zmeny?</string>
+    <string name="trim_video_exit_msg">Zahodiť zmeny vykonané v tomto videu?</string>
+    <string name="trim_video_exit_discard">ZRUŠIŤ</string>
+</resources>
diff --git a/res/values-sl/cm_strings.xml b/res/values-sl/cm_strings.xml
new file mode 100644
index 0000000..dca150d
--- /dev/null
+++ b/res/values-sl/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Čas snemanja</string>
+</resources>
diff --git a/res/values-sl/codeaurora_strings.xml b/res/values-sl/codeaurora_strings.xml
new file mode 100644
index 0000000..523fce8
--- /dev/null
+++ b/res/values-sl/codeaurora_strings.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Korak</string>
+    <string name="step_option_desc">Prilagodi korak za pomik najprej/nazaj</string>
+    <string name="setp_option_three_second">3 sekunde</string>
+    <string name="setp_option_six_second">6 sekund</string>
+    <string name="loop">"Zanka"</string>
+    <string name="single">"Posamezni"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">VKLOPI zvočnik</string>
+    <string name="speaker_off">IZKLOPI zvočnik</string>
+    <string name="speaker_need_headset">Priključite slušalke za uporabo te značilnosti.</string>
+    <string name="single_track">"Posamezna skladba"</string>
+    <string name="input_url">"Vnesite URL"</string>
+    <string name="streaming_settings">"Nastavitve pretakanja"</string>
+    <string name="next">"Naprej"</string>
+    <string name="previous">"Prejšnji"</string>
+    <string name="buffer_size">Velikost medpomnilnika</string>
+    <string name="apn">Priljubljeni APN</string>
+    <string name="rtp_min_port">Najmanjše št. vrat</string>
+    <string name="rtp_max_port">Največje št. vrat</string>
+    <string name="set_rtp_min_port">Nastavite najmanjše št . vrat</string>
+    <string name="set_rtp_max_port">Nastavite največje št . vrat</string>
+    <string name="set_buffer_size">Nastavite velikost medpomnilnika</string>
+    <string name="set_apn">Izberite priljubljeni APN</string>
+    <string name="setting">Nastavitve</string>
+    <string name="server_timeout_title">"Časovna omejitev strežnika"</string>
+    <string name="server_timeout_message">"Ponovno se poveži na strežnik za predvajanje videoposnetka?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Povezava je spodletela, poskušanje ponovne povezave na %1$d \u2026"</string>
+    <string name="media_controller_live">V živo</string>
+    <string name="media_controller_playing">Predvaja se</string>
+    <string name="media_controller_connecting">Povezovanje \u2026</string>
+    <string name="bookmark_add">"Dodaj zaznamek"</string>
+    <string name="bookmark_display">"Prikaži zaznamke"</string>
+    <string name="bookmark_empty">"Ni zaznamkov"</string>
+    <string name="bookmark_exist">"Zaznamek že obstaja"</string>
+    <string name="bookmark_add_success">"Zaznamek dodan"</string>
+    <string name="bookmark_list">"Zaznamki"</string>
+    <string name="bookmark_title">"Naslov"</string>
+    <string name="bookmark_location">"Mesto"</string>
+    <string name="delete_all">"Izbriši vse"</string>
+    <string name="default_title">"Privzeti naslov"</string>
+    <string name="more_image">Več slik</string>
+    <string name="mute_nosupport">Utišanje ni mogoče: videoposnetki niso podprti</string>
+    <string name="map_activity_not_found_err">Ni nameščene aplikacije za zemljevide, da bi se prikazala lokacija.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d videoposnetek</item>
+        <item quantity="two">%1$d videoposnetka</item>
+        <item quantity="few">%1$d videoposnetki</item>
+        <item quantity="other">%1$d videoposnetkov</item>
+    </plurals>
+    <string name="cannot_share_items">Največje število izbranih predmetov za deljenje je 300</string>
+    <string name="share_dialogue_title">Deli preko</string>
+    <string name="no_faces">Ni obrazov</string>
+    <string name="fail_trim">Žal te datoteke videoposnetka ni mogoče obrezati</string>
+    <string name="can_not_trim">Obrezane so lahko samo mp4 in 3gp datoteke</string>
+    <string name="drm_license_info">Podatki licence DRM</string>
+    <string name="timeline_title">Časovnica</string>
+    <string name="albums_title">Albumi</string>
+    <string name="videos_title">Videoposnetki</string>
+    <string name="action_viewtype_list">Seznamski pogled</string>
+    <string name="tvEmptyAlbum">Ni najdenih slik</string>
+    <string name="tvEmptyVideos">Ni najdenih videoposnetkov</string>
+    <string name="text_makeup_whiten">Pobeli</string>
+    <string name="text_makeup_Soften">Zmehčaj</string>
+    <string name="text_makeup_trimface">Obrezovanje obraza</string>
+    <string name="text_makeup_bigeye">Veliko oko</string>
+    <string name="truescanner_normal">Običajno</string>
+    <string name="truescanner_white">Bela tabla</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Odstranjevanje bleščanja</string>
+    <string name="hazebuster_acts">Odstranjevanje zamegljenosti</string>
+    <string name="seestraight_acts">Glejte naravnost</string>
+    <string name="seestraight_input_image_is_small">Vhodna slika je premajhna za obdelavo.</string>
+    <string name="seestraight_process_fail">Slike ni bilo mogoče obdelati.</string>
+    <string name="trim_video_exit_title">Zavrzi spremembe?</string>
+    <string name="trim_video_exit_msg">Zavrzi spremembe opravljene na tem videoposnetku?</string>
+    <string name="trim_video_exit_discard">ZAVRZI</string>
+</resources>
diff --git a/res/values-sq/cm_strings.xml b/res/values-sq/cm_strings.xml
new file mode 100644
index 0000000..e05de95
--- /dev/null
+++ b/res/values-sq/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Koha e regjistrimit</string>
+</resources>
diff --git a/res/values-sq/codeaurora_strings.xml b/res/values-sq/codeaurora_strings.xml
new file mode 100644
index 0000000..48c9a1a
--- /dev/null
+++ b/res/values-sq/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Hapi</string>
+    <string name="step_option_desc">Rregullo hapin e shpejtë përpara/mbrapa</string>
+    <string name="setp_option_three_second">3 sekonda</string>
+    <string name="setp_option_six_second">6 sekonda</string>
+    <string name="loop">"Cikël"</string>
+    <string name="single">"I vetëm"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Altoparlanti AKTIV</string>
+    <string name="speaker_off">Altoparlanti INAKTIV</string>
+    <string name="speaker_need_headset">Lidhni kufjet për të përdorur këtë funksion.</string>
+    <string name="single_track">"Pjesë e vetme"</string>
+    <string name="input_url">"Vendos URL-në"</string>
+    <string name="streaming_settings">"Cilësimet e transmetimit"</string>
+    <string name="next">"Tjetra"</string>
+    <string name="previous">"I Mëparshëm"</string>
+    <string name="buffer_size">Madhësia e tamponit</string>
+    <string name="apn">APN i preferuar</string>
+    <string name="rtp_min_port">Porta më e ulët</string>
+    <string name="rtp_max_port">Porta më e lartë</string>
+    <string name="set_rtp_min_port">Vendos portën më të ulët</string>
+    <string name="set_rtp_max_port">Vendos portën më të lartë</string>
+    <string name="set_buffer_size">Vendosni madhësinë e tamponit</string>
+    <string name="set_apn">Zgjidhni APN-në e preferuar</string>
+    <string name="setting">Cilësimet</string>
+    <string name="server_timeout_title">"Koha e ndërprerjes së serverit"</string>
+    <string name="server_timeout_message">"Rilidhuni me serverin për të luajtur videon?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Lidhja dështoi, duke u përpjekur të rilidhet me %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Duke luajtur</string>
+    <string name="media_controller_connecting">Po lidhet\u2026</string>
+    <string name="bookmark_add">"Shto faqeshënues"</string>
+    <string name="bookmark_display">"Shfaq faqeshënuesit"</string>
+    <string name="bookmark_empty">"Nuk ka faqeshënues"</string>
+    <string name="bookmark_exist">"Faqeshënuesi tashmë ekziston"</string>
+    <string name="bookmark_add_success">"Faqeshënuesi u shtua"</string>
+    <string name="bookmark_list">"Faqeshënuesit"</string>
+    <string name="bookmark_title">"Titulli"</string>
+    <string name="bookmark_location">"Vendndodhja"</string>
+    <string name="delete_all">"Fshiji të gjitha"</string>
+    <string name="default_title">"Titulli i paracaktuar"</string>
+    <string name="more_image">Më shumë imazhe</string>
+    <string name="mute_nosupport">Nuk mund t\'i heqësh zërin : video nuk është e pranueshme</string>
+    <string name="map_activity_not_found_err">Nuk ka asnjë aplikacion hartash të intaluar që të tregojë vendndodhjen.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Maksimumi i lejuar për të shpërndarë është 300</string>
+    <string name="share_dialogue_title">Ndaj me anë të</string>
+    <string name="no_faces">Pa foto</string>
+    <string name="fail_trim">Na vjen keq, por kjo video nuk mund të shkurtohet</string>
+    <string name="can_not_trim">Vetëm skedarët me format mp4 dhe mp3 mund të shkurtohen</string>
+    <string name="drm_license_info">Informacion rreth liçensës DRM</string>
+    <string name="timeline_title">Vija kohore</string>
+    <string name="albums_title">Albumet</string>
+    <string name="videos_title">Videot</string>
+    <string name="action_viewtype_list">Paraqit si liste</string>
+    <string name="tvEmptyAlbum">Nuk u gjet asnjë foto</string>
+    <string name="tvEmptyVideos">Nuk u gjet asnjë video</string>
+    <string name="text_makeup_whiten">Zbardh</string>
+    <string name="text_makeup_Soften">Zbut</string>
+    <string name="text_makeup_trimface">Sajdisje</string>
+    <string name="text_makeup_bigeye">Sy të mëdhenj</string>
+    <string name="truescanner_normal">Normale</string>
+    <string name="truescanner_white">Faqe e bardhë</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Hiq shkëlqimin</string>
+    <string name="hazebuster_acts">Heq mjegullimin</string>
+    <string name="seestraight_acts">Shiko drejt</string>
+    <string name="seestraight_input_image_is_small">Imazhi i vendosur është shumë i vogël per tu përpunuar.</string>
+    <string name="seestraight_process_fail">Nuk mund të përpunohej imazhi.</string>
+    <string name="trim_video_exit_title">Shpërfill ndryshimet?</string>
+    <string name="trim_video_exit_msg">Shpërfill ndryshimet e bëra në këtë video?</string>
+    <string name="trim_video_exit_discard">SHPËRFILL</string>
+</resources>
diff --git a/res/values-sr/cm_strings.xml b/res/values-sr/cm_strings.xml
new file mode 100644
index 0000000..18ca2f1
--- /dev/null
+++ b/res/values-sr/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Време снимања</string>
+</resources>
diff --git a/res/values-sr/codeaurora_strings.xml b/res/values-sr/codeaurora_strings.xml
new file mode 100644
index 0000000..1ff0a82
--- /dev/null
+++ b/res/values-sr/codeaurora_strings.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Корак</string>
+    <string name="step_option_desc">Подесите интервал за брзо премотавање унапред или уназад</string>
+    <string name="setp_option_three_second">3 секунде</string>
+    <string name="setp_option_six_second">6 секунди</string>
+    <string name="loop">"Понављање"</string>
+    <string name="single">"Појединачно"</string>
+    <string name="stereo">"Стерео"</string>
+    <string name="speaker_on">Укључен звучник</string>
+    <string name="speaker_off">Искључен звучник</string>
+    <string name="speaker_need_headset">Прикључите слушалице за коришћење ове функције.</string>
+    <string name="single_track">"Једна нумера"</string>
+    <string name="input_url">"Унесите URL"</string>
+    <string name="streaming_settings">"Подешавања стриминга"</string>
+    <string name="next">"Следећа"</string>
+    <string name="previous">"Претходна"</string>
+    <string name="buffer_size">Величина бафера</string>
+    <string name="apn">Жељени APN</string>
+    <string name="rtp_min_port">Минимални порт</string>
+    <string name="rtp_max_port">Максимални порт</string>
+    <string name="set_rtp_min_port">Поставите мин. број порта</string>
+    <string name="set_rtp_max_port">Поставите макс. број порта</string>
+    <string name="set_buffer_size">Поставите величину бафера</string>
+    <string name="set_apn">Изаберите жељени APN</string>
+    <string name="setting">Поставке</string>
+    <string name="server_timeout_title">"Време истека сервера"</string>
+    <string name="server_timeout_message">"Поново се повезати са сервером за репродуковање видео снимка?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Грешка у вези. Поново се повезујем са %1$d\u2026"</string>
+    <string name="media_controller_live">Уживо</string>
+    <string name="media_controller_playing">Репродукција</string>
+    <string name="media_controller_connecting">Повезујем се\u2026</string>
+    <string name="bookmark_add">"Додај обележивач"</string>
+    <string name="bookmark_display">"Прикажи обележиваче"</string>
+    <string name="bookmark_empty">"Нема обележивача"</string>
+    <string name="bookmark_exist">"Обележивач већ постоји"</string>
+    <string name="bookmark_add_success">"Обележивач додат"</string>
+    <string name="bookmark_list">"Обележивачи"</string>
+    <string name="bookmark_title">"Наслов"</string>
+    <string name="bookmark_location">"Локација"</string>
+    <string name="delete_all">"Избриши све"</string>
+    <string name="default_title">"Подразумевани наслов"</string>
+    <string name="more_image">Још слика</string>
+    <string name="mute_nosupport">Не могу да искључим звук: видео није подржан</string>
+    <string name="map_activity_not_found_err">Не могу да прикажем локацију јер апликација за рад са мапама није инсталирана.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d видео-снимак</item>
+        <item quantity="few">%1$d видео-снимка</item>
+        <item quantity="other">%1$d видео-снимака</item>
+    </plurals>
+    <string name="cannot_share_items">Максималан број изабраних ставки за дељење је 300.</string>
+    <string name="share_dialogue_title">Начин дељења</string>
+    <string name="no_faces">Без лица</string>
+    <string name="fail_trim">Нажалост, видео снимак не може бити скраћен</string>
+    <string name="can_not_trim">Можете скратити само датотеке у форматима MP4 и 3GP.</string>
+    <string name="drm_license_info">Информације о DRM лиценци</string>
+    <string name="timeline_title">Хронолошки след</string>
+    <string name="albums_title">Албуми</string>
+    <string name="videos_title">Видео</string>
+    <string name="action_viewtype_list">Приказ списка</string>
+    <string name="tvEmptyAlbum">Нема фотографија.</string>
+    <string name="tvEmptyVideos">Нема видео-снимака.</string>
+    <string name="text_makeup_whiten">Избељивање</string>
+    <string name="text_makeup_Soften">Омекшавање</string>
+    <string name="text_makeup_trimface">Опсецање лица</string>
+    <string name="text_makeup_bigeye">Велике очи</string>
+    <string name="truescanner_normal">Нормално</string>
+    <string name="truescanner_white">Бела табла</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Уклони одсјај</string>
+    <string name="hazebuster_acts">Уклони замагљеност</string>
+    <string name="seestraight_acts">Гледај право</string>
+    <string name="seestraight_input_image_is_small">Слика је премала за обраду.</string>
+    <string name="seestraight_process_fail">Не могу да обрадим слику.</string>
+    <string name="trim_video_exit_title">Одбацивање измена</string>
+    <string name="trim_video_exit_msg">Одбацити измене направљене на овом видео-снимку?</string>
+    <string name="trim_video_exit_discard">ОДБАЦИ</string>
+</resources>
diff --git a/res/values-sv/cm_strings.xml b/res/values-sv/cm_strings.xml
new file mode 100644
index 0000000..24164f7
--- /dev/null
+++ b/res/values-sv/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Inspelningstid</string>
+</resources>
diff --git a/res/values-sv/codeaurora_strings.xml b/res/values-sv/codeaurora_strings.xml
new file mode 100644
index 0000000..fc18259
--- /dev/null
+++ b/res/values-sv/codeaurora_strings.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Steg</string>
+    <string name="step_option_desc">Anpassa snabbspolningssteg framåt/bakåt</string>
+    <string name="setp_option_three_second">3 sekunder</string>
+    <string name="setp_option_six_second">6 sekunder</string>
+    <string name="loop">"Repetera"</string>
+    <string name="single">"Enkel"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Högtalare PÅ</string>
+    <string name="speaker_off">Högtalare AV</string>
+    <string name="speaker_need_headset">Anslut hörlurarna för att använda denna funktion.</string>
+    <string name="single_track">"Enkelt spår"</string>
+    <string name="input_url">"Ange URL"</string>
+    <string name="streaming_settings">"Inställningar för direktuppspelning"</string>
+    <string name="next">"Nästa"</string>
+    <string name="previous">"Föregående"</string>
+    <string name="buffer_size">Bufferstorlek</string>
+    <string name="apn">Förvald APN</string>
+    <string name="rtp_min_port">Lägsta portnummer</string>
+    <string name="rtp_max_port">Högsta portnummer</string>
+    <string name="set_rtp_min_port">Ange lägsta portnummer</string>
+    <string name="set_rtp_max_port">Ange högsta portnummer</string>
+    <string name="set_buffer_size">Ange buffertstorlek</string>
+    <string name="set_apn">Välj önskad APN</string>
+    <string name="setting">Inställningar</string>
+    <string name="server_timeout_title">"Server-timeout"</string>
+    <string name="server_timeout_message">"Återanslut till servern för att spela videon?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Anslutning misslyckades, försöker återansluta till %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Spelar</string>
+    <string name="media_controller_connecting">Ansluter\u2026</string>
+    <string name="bookmark_add">"Lägg till bokmärke"</string>
+    <string name="bookmark_display">"Visa bokmärken"</string>
+    <string name="bookmark_empty">"Inga bokmärken"</string>
+    <string name="bookmark_exist">"Bokmärket finns redan"</string>
+    <string name="bookmark_add_success">"Bokmärke tillagt"</string>
+    <string name="bookmark_list">"Bokmärken"</string>
+    <string name="bookmark_title">"Titel"</string>
+    <string name="bookmark_location">"Plats"</string>
+    <string name="delete_all">"Ta bort alla"</string>
+    <string name="default_title">"Förvald titel"</string>
+    <string name="more_image">Fler bilder</string>
+    <string name="mute_nosupport">Kan inte stänga av ljudet: video stöds inte</string>
+    <string name="map_activity_not_found_err">Det finns ingen kartapplikation installerad för att visa platsen.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videor</item>
+    </plurals>
+    <string name="share_dialogue_title">Dela via</string>
+    <string name="no_faces">Inga ansikten</string>
+    <string name="fail_trim">Tyvärr, denna videofil kan inte klippas</string>
+    <string name="drm_license_info">Information om DRM-licens</string>
+    <string name="timeline_title">Tidslinje</string>
+    <string name="albums_title">Album</string>
+    <string name="videos_title">Videor</string>
+    <string name="action_viewtype_list">Listvy</string>
+    <string name="tvEmptyAlbum">Inga foton hittades</string>
+    <string name="tvEmptyVideos">Inga videor hittades</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="trim_video_exit_discard">AVBRYT</string>
+</resources>
diff --git a/res/values-ta/cm_strings.xml b/res/values-ta/cm_strings.xml
new file mode 100644
index 0000000..4b30495
--- /dev/null
+++ b/res/values-ta/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">பதிவேடு நேரம்</string>
+</resources>
diff --git a/res/values-ta/codeaurora_strings.xml b/res/values-ta/codeaurora_strings.xml
new file mode 100644
index 0000000..8e0eb28
--- /dev/null
+++ b/res/values-ta/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">படிநிலை</string>
+    <string name="step_option_desc">வேகமாக முன்செல்லுதல்/பின்செல்லுதல் படியை தனிப்பயனாக்கு</string>
+    <string name="setp_option_three_second">3 நொடிகள்</string>
+    <string name="setp_option_six_second">6 நொடிகள்</string>
+    <string name="loop">""சுழற்சி""</string>
+    <string name="single">""ஒற்றை""</string>
+    <string name="stereo">""ஸ்டீரியோ""</string>
+    <string name="speaker_on">ஒலிப்பெருக்கி ஆன்</string>
+    <string name="speaker_off">ஒலிப்பெருக்கி ஆஃப்</string>
+    <string name="speaker_need_headset">இந்த அம்சத்தைப் பயன்படுத்த தலையணியை ப்ளக்-இன்</string>
+    <string name="single_track">""ஒற்றைத் தடம்""</string>
+    <string name="input_url">"“உள்ளிடு URL”"</string>
+    <string name="streaming_settings">"“ஸ்ட்ரீமிங் அமைப்புகள்”"</string>
+    <string name="next">""அடுத்து""</string>
+    <string name="previous">""முந்தைய""</string>
+    <string name="buffer_size">இடையக அளவு</string>
+    <string name="apn">விருப்பமான APN</string>
+    <string name="rtp_min_port">குறைந்தபட்ச முனையம்</string>
+    <string name="rtp_max_port">அதிகபட்ச முனையம்</string>
+    <string name="set_rtp_min_port">குறைந்தபட்ச முனையத்தை அமை</string>
+    <string name="set_rtp_max_port">அதிகபட்ச முனையத்தை அமை</string>
+    <string name="set_buffer_size">இடையக அளவை அமை</string>
+    <string name="set_apn">விருப்பமான APNஐ தேர்வுசெய்</string>
+    <string name="setting">அமைப்புகள்</string>
+    <string name="server_timeout_title">"“சேவையகம் நெரம் முடிந்தது”"</string>
+    <string name="server_timeout_message">"”வீடியோவை இயக்க சேவையகத்துடன் மறு இணைப்பு செயவா?”"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"“இணைப்பு தோல்வியுற்றது, மீண்டும் மறு இணைப்பு செய்ய முயற்சிக்கிறது%1$d\u2026""</string>
+    <string name="media_controller_live">நேரலை</string>
+    <string name="media_controller_playing">இயங்குகிறது</string>
+    <string name="media_controller_connecting">இணைக்கிறது...</string>
+    <string name="bookmark_add">""அடையாளக்குறியைச் சேர்""</string>
+    <string name="bookmark_display">""அடையாளக்குறிகளைக் காண்பி""</string>
+    <string name="bookmark_empty">""அடையாளக்குறிகள் இல்லை""</string>
+    <string name="bookmark_exist">"”அடையாளக்குறி முன்பே இருக்கிறது”"</string>
+    <string name="bookmark_add_success">"“அடையாளக்குறி சேர்க்கப்பட்டது”"</string>
+    <string name="bookmark_list">""அடையாளக்குறிகள்""</string>
+    <string name="bookmark_title">""தலைப்பு""</string>
+    <string name="bookmark_location">""இருப்பிடம்""</string>
+    <string name="delete_all">""அனைத்தையும் நீக்கு""</string>
+    <string name="default_title">""இயல்புநிலைத் தலைப்பு""</string>
+    <string name="more_image">அதிக படங்கள்</string>
+    <string name="mute_nosupport">ஒலிதடுக்க முடியாது: வீடியோ ஆதரிக்கப்படவில்லை</string>
+    <string name="map_activity_not_found_err">இடத்தை காண்பிக்க வரைபட பயன்பாடு நிறுவப்படவில்லை</string>
+    <string name="fail_trim">மன்னிக்கவும், இந்த வீடியோ இயக்க முடியாது</string>
+    <string name="drm_license_info">DRM உரிம தகவல்</string>
+</resources>
diff --git a/res/values-te/cm_strings.xml b/res/values-te/cm_strings.xml
new file mode 100644
index 0000000..9d645f0
--- /dev/null
+++ b/res/values-te/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">భద్ర పరచు సమయం</string>
+</resources>
diff --git a/res/values-te/codeaurora_strings.xml b/res/values-te/codeaurora_strings.xml
new file mode 100644
index 0000000..459d19f
--- /dev/null
+++ b/res/values-te/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">దశ</string>
+    <string name="step_option_desc">వేగంగా ముందుకెళ్లు/వెనక్కి వెళ్లు దశను అనుకూలీకరించుము</string>
+    <string name="setp_option_three_second">3 సెకనులు</string>
+    <string name="setp_option_six_second">6 సెకనులు</string>
+    <string name="loop">""లూప్""</string>
+    <string name="single">""సింగిల్""</string>
+    <string name="stereo">""స్టీరియో""</string>
+    <string name="speaker_on">స్పీకర్ ఆన్</string>
+    <string name="speaker_off">స్పీకర్ ఆఫ్</string>
+    <string name="speaker_need_headset">ఈ లక్షణాన్ని ఉపయోగించేందుకు హెడ్‌ఫోన్లను ప్లగ్-ఇన్ చేయండి.</string>
+    <string name="single_track">""సింగిల్ ట్రాక్""</string>
+    <string name="input_url">"“URLను ఎంటర్ చేయండి”"</string>
+    <string name="streaming_settings">"“ప్రసార సెట్టింగులు”"</string>
+    <string name="next">""తదుపరి""</string>
+    <string name="previous">""మునుపటి""</string>
+    <string name="buffer_size">బఫర్ పరిమాణం</string>
+    <string name="apn">కావలసిన APN</string>
+    <string name="rtp_min_port">కనిష్ఠ పోర్ట్</string>
+    <string name="rtp_max_port">గరిష్ఠ పోర్ట్</string>
+    <string name="set_rtp_min_port">కనిష్ఠ పోర్టును సెట్ చేయండి</string>
+    <string name="set_rtp_max_port">గరిష్ఠ పోర్టును సెట్ చేయండి</string>
+    <string name="set_buffer_size">బఫర్ పరిమాణాన్ని సెట్ చేయండి</string>
+    <string name="set_apn">కావలసిన APNను ఎంచుకొనుము</string>
+    <string name="setting">సెట్టింగ్‌లు</string>
+    <string name="server_timeout_title">"“సర్వర్ టైమవుట్""</string>
+    <string name="server_timeout_message">""వీడియోను ప్లే చేసేందుకు సర్వరుకు తిరిగి అనుసంధానం చేయాలా?”"</string>
+    <string name="videoview_error_text_cannot_connect_retry">""అనుసంధానం విఫలమయింది, %1$dకి మరలా అనుసంధానించడానికి ప్రయత్నిస్తోంది\u2026""</string>
+    <string name="media_controller_live">ప్రత్యక్ష</string>
+    <string name="media_controller_playing">ప్లే ఔతోంది</string>
+    <string name="media_controller_connecting">కనెక్ట్ చేస్తోంది...</string>
+    <string name="bookmark_add">""బుక్‌మార్క్ చేర్చు""</string>
+    <string name="bookmark_display">""బుక్‌మార్క్‌లను చూపించు""</string>
+    <string name="bookmark_empty">""బుక్ మార్కులు లేవు""</string>
+    <string name="bookmark_exist">"“పుటసూచి ఇప్పటికే ఉంది”"</string>
+    <string name="bookmark_add_success">""పుటసూచి జోడించబడింది”"</string>
+    <string name="bookmark_list">""బుక్‌మార్కులు""</string>
+    <string name="bookmark_title">""శీర్షిక""</string>
+    <string name="bookmark_location">""స్థానం""</string>
+    <string name="delete_all">""అన్నీ తొలగించు""</string>
+    <string name="default_title">""డిఫాల్ట్ శీర్షిక""</string>
+    <string name="more_image">మరిన్ని చిత్రాలు</string>
+    <string name="mute_nosupport">నిశ్శబ్దం చేయడం సాధ్యపడదు: వీడియోకు మద్దతు లేదు</string>
+    <string name="map_activity_not_found_err">స్థానాన్ని చూపించేందుకు మ్యాప్స్ అనువర్తనం వ్యవస్థాపించబడిలేదు.</string>
+    <string name="fail_trim">క్షమించండి, ఈ వీడియో ఫైలును కత్తిరించడం కుదరదు</string>
+    <string name="drm_license_info">DRM లైసెన్స్ సమాచారం</string>
+</resources>
diff --git a/res/values-th/cm_strings.xml b/res/values-th/cm_strings.xml
new file mode 100644
index 0000000..ee2d8d5
--- /dev/null
+++ b/res/values-th/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">เวลาบันทึก</string>
+</resources>
diff --git a/res/values-th/codeaurora_strings.xml b/res/values-th/codeaurora_strings.xml
new file mode 100644
index 0000000..6e0f4ee
--- /dev/null
+++ b/res/values-th/codeaurora_strings.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ขั้นตอน</string>
+    <string name="step_option_desc">ปรับแต่งการไปข้างหน้า/การถอยกลับ</string>
+    <string name="setp_option_three_second">3 วินาที</string>
+    <string name="setp_option_six_second">6 วินาที</string>
+    <string name="loop">"วน"</string>
+    <string name="single">"เดี่ยว"</string>
+    <string name="stereo">"สเตอริโอ"</string>
+    <string name="speaker_on">เปิดลำโพง</string>
+    <string name="speaker_off">ปิดลำโพง</string>
+    <string name="speaker_need_headset">เสียบหูฟังเพื่อใช้คุณสมบัตินี้</string>
+    <string name="single_track">"แทรคเดี่ยว"</string>
+    <string name="input_url">"ป้อน URL"</string>
+    <string name="streaming_settings">"การตั้งค่าสตรีมมิ่ง"</string>
+    <string name="next">"ถัดไป"</string>
+    <string name="previous">"ก่อนหน้า"</string>
+    <string name="buffer_size">ขนาดของบัฟเฟอร์</string>
+    <string name="apn">APN ที่ต้องการ</string>
+    <string name="rtp_min_port">พอร์ตต่ำสุด</string>
+    <string name="rtp_max_port">พอร์ตสูงสุด</string>
+    <string name="set_rtp_min_port">ตั้งพอร์ตต่ำสุด</string>
+    <string name="set_rtp_max_port">ตั้งพอร์ดสูงสุด</string>
+    <string name="set_buffer_size">ตั้งขนาดบัฟเฟอร์</string>
+    <string name="set_apn">เลือก APN ที่ต้องการ</string>
+    <string name="setting">การตั้งค่า</string>
+    <string name="server_timeout_title">"หมดเวลาเชื่อมต่อเซิฟเวอร์"</string>
+    <string name="server_timeout_message">"เชื่อมต่อกับเซิร์ฟเวอร์อีกครั้งเพื่อเล่นวิดีโอหรือไม่"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"เชื่อมต่อล้มเหลว พยายามเชื่อมต่ออีกครั้งไปที่ %1$d\u2026"</string>
+    <string name="media_controller_live">ถ่ายทอดสด</string>
+    <string name="media_controller_playing">กำลังเล่น</string>
+    <string name="media_controller_connecting">กำลังเชื่อมต่อ\u2026</string>
+    <string name="bookmark_add">"เพิ่มคั่นหน้า"</string>
+    <string name="bookmark_display">"แสดงบุ๊คมาร์ค"</string>
+    <string name="bookmark_empty">"ไม่มีบุ๊คมาร์ค"</string>
+    <string name="bookmark_exist">"มีบุ๊คมาร์คอยู่แล้ว"</string>
+    <string name="bookmark_add_success">"เพิ่มบุ๊คมาร์คแล้ว"</string>
+    <string name="bookmark_list">"บุ๊คมาร์ค"</string>
+    <string name="bookmark_title">"ชื่อเรื่อง"</string>
+    <string name="bookmark_location">"ตำแหน่งที่ตั้ง"</string>
+    <string name="delete_all">"ลบทั้งหมด"</string>
+    <string name="default_title">"ชื่อเริ่มต้น"</string>
+    <string name="more_image">ภาพเพิ่มเติม</string>
+    <string name="mute_nosupport">ไม่สามารถปิดเสียงได้ : วิดีโอไม่รองรับ</string>
+    <string name="map_activity_not_found_err">ไม่มีแอปแผนที่ติดตั้งอยู่เพื่อใช้แสดงตำแหน่งที่ตั้ง</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d วิดีโอ</item>
+    </plurals>
+    <string name="cannot_share_items">เลือกรายการแบ่งปันได้สูงสุด 300 ตัวเลือก</string>
+    <string name="share_dialogue_title">แบ่งปันผ่านทาง</string>
+    <string name="no_faces">ไม่พบใบหน้า</string>
+    <string name="fail_trim">ขออภัย ไม่สามารถตัดแต่งวิดีโอนี้ได้</string>
+    <string name="can_not_trim">ตัดได้เฉพาะไฟล์ mp4 และ 3gp</string>
+    <string name="drm_license_info">ข้อมูลสิทธิ์การใช้ DRM</string>
+    <string name="timeline_title">ไทม์ไลน์</string>
+    <string name="albums_title">อัลบั้ม</string>
+    <string name="videos_title">วิดีโอ</string>
+    <string name="action_viewtype_list">มุมมองรายการ</string>
+    <string name="tvEmptyAlbum">ไม่พบรูปภาพ</string>
+    <string name="tvEmptyVideos">ไม่พบวิดีโอ</string>
+    <string name="text_makeup_whiten">ทำให้ขาวขึ้น</string>
+    <string name="text_makeup_Soften">ทำให้นุ่มนวล</string>
+    <string name="text_makeup_bigeye">ตาโต</string>
+    <string name="truescanner_normal">ปกติ</string>
+    <string name="truescanner_white">กระดานไวท์บอร์ด</string>
+    <string name="truescanner_remove_glare">ลบแสงจ้า</string>
+    <string name="seestraight_acts">ทำให้ตรง</string>
+    <string name="seestraight_input_image_is_small">ภาพที่นำเข้ามีขนาดเล็กเกินไปที่จะประมวลผล</string>
+    <string name="seestraight_process_fail">ไม่สามารถประมวลผลภาพได้</string>
+    <string name="trim_video_exit_title">ยก​เลิก​การ​เปลี่ยน​แปลงหรือไม่</string>
+    <string name="trim_video_exit_discard">ยกเลิก</string>
+</resources>
diff --git a/res/values-tr/cm_strings.xml b/res/values-tr/cm_strings.xml
new file mode 100644
index 0000000..2f72639
--- /dev/null
+++ b/res/values-tr/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Kayıt zamanı</string>
+</resources>
diff --git a/res/values-tr/codeaurora_strings.xml b/res/values-tr/codeaurora_strings.xml
new file mode 100644
index 0000000..a60b903
--- /dev/null
+++ b/res/values-tr/codeaurora_strings.xml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Aralık</string>
+    <string name="step_option_desc">Hızlı ileri/geri sarma aralıklarını özelleştir</string>
+    <string name="setp_option_three_second">3 saniye</string>
+    <string name="setp_option_six_second">6 saniye</string>
+    <string name="loop">"Döngü"</string>
+    <string name="single">"Tek"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Hoparlör AÇIK</string>
+    <string name="speaker_off">Hoparlör KAPALI</string>
+    <string name="speaker_need_headset">Bu özelliği kullanmak için kulaklık takın.</string>
+    <string name="single_track">"Tek parça"</string>
+    <string name="input_url">"URL girin"</string>
+    <string name="streaming_settings">"Akış ayarları"</string>
+    <string name="next">"Sonraki"</string>
+    <string name="previous">"Önceki"</string>
+    <string name="buffer_size">Ara bellek boyutu</string>
+    <string name="apn">Tercih edilen APN</string>
+    <string name="rtp_min_port">Min bağlantı noktası</string>
+    <string name="rtp_max_port">Maks bağlantı noktası</string>
+    <string name="set_rtp_min_port">Min bağlantı noktasını ayarla</string>
+    <string name="set_rtp_max_port">Max bağlantı noktasını ayarla</string>
+    <string name="set_buffer_size">Ara bellek boyutunu ayarla</string>
+    <string name="set_apn">Tercih edilen APN\'yi seçin</string>
+    <string name="setting">Ayarlar</string>
+    <string name="server_timeout_title">"Sunucu zaman aşımı"</string>
+    <string name="server_timeout_message">"Videoyu oynatmak için sunucuya yeniden bağlanılsın mı?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Bağlantı başarısız, %1$d için yeniden bağlantı kuruluyor\u2026"</string>
+    <string name="media_controller_live">Canlı</string>
+    <string name="media_controller_playing">Çalınıyor</string>
+    <string name="media_controller_connecting">Bağlanıyor\u2026</string>
+    <string name="bookmark_add">"Yer işareti ekle"</string>
+    <string name="bookmark_display">"Yer işaretlerini göster"</string>
+    <string name="bookmark_empty">"Yer işareti yok"</string>
+    <string name="bookmark_exist">"Yer işareti zaten var"</string>
+    <string name="bookmark_add_success">"Yer işareti eklendi"</string>
+    <string name="bookmark_list">"Yer işaretleri"</string>
+    <string name="bookmark_title">"Başlık"</string>
+    <string name="bookmark_location">"Konum"</string>
+    <string name="delete_all">"Tümünü sil"</string>
+    <string name="default_title">"Varsayılan başlık"</string>
+    <string name="more_image">Daha çok resim</string>
+    <string name="mute_nosupport">Susturulamıyor : video desteklemiyor</string>
+    <string name="map_activity_not_found_err">Konum göstermek için yüklü harita uygulaması yok.</string>
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Paylaşım için seçilebilecek maksimum öğe sayısı 300\'dür</string>
+    <string name="share_dialogue_title">Şununla paylaş</string>
+    <string name="no_faces">Yüz yok</string>
+    <string name="fail_trim">Üzgünüz, bu video kesilemiyor</string>
+    <string name="can_not_trim">Sadece mp4 ve 3gp dosyaları kesilebilir</string>
+    <string name="drm_license_info">DHY lisans bilgisi</string>
+    <string name="timeline_title">Zaman Tüneli</string>
+    <string name="albums_title">Albümler</string>
+    <string name="videos_title">Videolar</string>
+    <string name="action_viewtype_list">Liste görünümü</string>
+    <string name="tvEmptyAlbum">Fotoğraf bulunamadı</string>
+    <string name="tvEmptyVideos">Video bulunamadı</string>
+    <string name="text_makeup_whiten">Beyazlat</string>
+    <string name="text_makeup_Soften">Yumuşat</string>
+    <string name="text_makeup_trimface">Yüz Kırpma</string>
+    <string name="text_makeup_bigeye">Büyük göz</string>
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Beyaz tahta</string>
+    <string name="truescanner">Gerçek Tarama</string>
+    <string name="truescanner_remove_glare">Parlamayı Kaldır</string>
+    <string name="hazebuster_acts">Pus Giderici</string>
+    <string name="seestraight_acts">Düz Bak</string>
+    <string name="seestraight_input_image_is_small">Resim, işlenemeyecek kadar küçük.</string>
+    <string name="seestraight_process_fail">Resim işlenemedi.</string>
+    <string name="trim_video_exit_title">Değişiklikler iptal edilsin mi?</string>
+    <string name="trim_video_exit_msg">Bu videoya yapılan değişiklikler iptal edilsin mi?</string>
+    <string name="trim_video_exit_discard">İPTAL</string>
+</resources>
diff --git a/res/values-ug/cm_strings.xml b/res/values-ug/cm_strings.xml
new file mode 100644
index 0000000..015f508
--- /dev/null
+++ b/res/values-ug/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">خاتىرىلىگەن ۋاقىت</string>
+</resources>
diff --git a/res/values-ug/codeaurora_strings.xml b/res/values-ug/codeaurora_strings.xml
new file mode 100644
index 0000000..b58eaa3
--- /dev/null
+++ b/res/values-ug/codeaurora_strings.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">ئارىلىق</string>
+    <string name="step_option_desc">ئىختىيارىي تېز ئالدىغا/كەينىگە ئارىلىقى</string>
+    <string name="setp_option_three_second">3 سېكۇنت</string>
+    <string name="setp_option_six_second">6 سېكۇنت</string>
+    <string name="loop">"دەۋرىي"</string>
+    <string name="single">"يەككە"</string>
+    <string name="stereo">"سىتېرېئو"</string>
+    <string name="speaker_on">ياڭراتقۇ ئوچۇق</string>
+    <string name="speaker_off">ياڭراتقۇ تاقاق</string>
+    <string name="speaker_need_headset">بۇ ئىقتىدارنى ئىشلىتىش ئۈچۈن تىڭشىغۇچنى قىستۇرۇڭ.</string>
+    <string name="single_track">"يەككە ئاۋاز يولى"</string>
+    <string name="input_url">"URL كىرگۈزۈڭ"</string>
+    <string name="streaming_settings">"ئېقىم تەڭشەكلەر"</string>
+    <string name="next">"كېيىنكى"</string>
+    <string name="previous">"ئالدىنقى"</string>
+    <string name="buffer_size">غەملەك چوڭلۇقى</string>
+    <string name="apn">ئالدىن تاللانغان APN</string>
+    <string name="rtp_min_port">ئەڭ كىچىك ئېغىز</string>
+    <string name="rtp_max_port">ئەڭ چوڭ ئېغىز</string>
+    <string name="set_rtp_min_port">ئەڭ كىچىك ئېغىز تەڭشىكى</string>
+    <string name="set_rtp_max_port">ئەڭ چوڭ ئېغىز تەڭشىكى</string>
+    <string name="set_buffer_size">غەملەك چوڭلۇق تەڭشىكى</string>
+    <string name="set_apn">ئالدىن بەلگىلەنگەن APN نى تاللاڭ</string>
+    <string name="setting">تەڭشەكلەر</string>
+    <string name="server_timeout_title">"مۇلازىمىتىر ۋاقىت ھالقىدى"</string>
+    <string name="server_timeout_message">"سىن قويۇشنى داۋاملاشتۇرۇش ئۈچۈن مۇلازىمېتىرغا قايتا ئۇلىنامدۇ؟"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"باغلىنالمىدى، %1$d غا قايتا ئۇلىنىشنى سىناۋاتىدۇ\u2026"</string>
+    <string name="media_controller_live">بىۋاستە</string>
+    <string name="media_controller_playing">چېلىۋاتىدۇ</string>
+    <string name="media_controller_connecting">ئۇلىنىۋاتىدۇ\u2026</string>
+    <string name="bookmark_add">"خەتكۈچ قوش"</string>
+    <string name="bookmark_display">"خەتكۈچ كۆرسەت"</string>
+    <string name="bookmark_empty">"خەتكۈچ يوق"</string>
+    <string name="bookmark_exist">"خەتكۈچ مەۋجۇت"</string>
+    <string name="bookmark_add_success">"خەتكۈچ قوشۇلدى"</string>
+    <string name="bookmark_list">"خەتكۈچلەر"</string>
+    <string name="bookmark_title">"ماۋزۇ"</string>
+    <string name="bookmark_location">"ئورنى"</string>
+    <string name="delete_all">"ھەممىنى ئۆچۈر"</string>
+    <string name="default_title">"كۆڭۈلدىكى ماۋزۇ"</string>
+    <string name="more_image">تېخىمۇ كۆپ سۈرەت</string>
+    <string name="mute_nosupport">ئۈنسىز قىلغىلى بولمايدۇ: سىننى قوللىمايدۇ</string>
+    <string name="map_activity_not_found_err">ئورنىنى كۆرسىتىشكە ئىشلىتىدىغان خەرىتە ئەپنى تاپالمىدى.</string>
+    <string name="fail_trim">كەچۈرۈڭ، بۇ سىن ھۆججىتىنى كەسكىلى بولمايدۇ</string>
+    <string name="drm_license_info">DRM ئىجازەتنامە ئۇچۇرى</string>
+</resources>
diff --git a/res/values-ug/filtershow_strings.xml b/res/values-ug/filtershow_strings.xml
new file mode 100644
index 0000000..2b8769a
--- /dev/null
+++ b/res/values-ug/filtershow_strings.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <string name="title_activity_filter_show">سۈرەت تەھرىرلىگۈچ</string>
+    <string name="cannot_load_image">بۇ سۈرەتنى يۈكلىيەلمەيدۇ!</string>
+    <string name="cannot_edit_original">دەسلەپكى نۇسخىنى تەھرىرلىيەلمەيدۇ</string>
+    <string name="setting_wallpaper">تام قەغەزنى تەڭشەۋاتىدۇ</string>
+    <string name="download_failure">سۈرەتنى چۈشۈرەلمەيدۇ. تورنى ئىشلەتكىلى بولمايدۇ.</string>
+    <string name="original">ئەسلى</string>
+    <string name="custom_border">ئىختىيارىي</string>
+    <string name="filtershow_undo">يېنىۋال</string>
+    <string name="filtershow_redo">قايتىلا</string>
+    <string name="show_imagestate_panel">قوللانغان ئۈنۈملەرنى كۆرسەت</string>
+    <string name="hide_imagestate_panel">قوللانغان ئۈنۈملەرنى يوشۇر</string>
+    <string name="export_image">چىقار</string>
+    <string name="print_image">باس</string>
+    <string name="export_flattened">جىپىسلىغان سۈرەتنى چىقار</string>
+    <string name="select_output_settings">چىقىرىلغان سۈرەت كۆچۈرۈلمە نۇسخا، ھېچقانداق تەھرىرلەش خاتىرىسىنى ئۆز ئىچىگە ئالمايدۇ.</string>
+    <string name="quality">سۈپەت</string>
+    <string name="size">چوڭلۇقى</string>
+    <string name="x">x</string>
+    <string name="menu_settings">تەڭشەكلەر</string>
+    <string name="unsaved">بۇ سۈرەتنىڭ ساقلانمىغان ئۆزگەرتىشلىرى بار.</string>
+    <string name="save_before_exit">چېكىنىش ئاۋۋال ساقلامسىز؟</string>
+    <string name="save_and_exit">ساقلاپ چېكىن</string>
+    <string name="save_and_processing">ئەسلى ئېنىقلىقتىكى سۈرەتنى بىر تەرەپ قىلىۋاتىدۇ…</string>
+    <string name="exit">چېكىن</string>
+    <string name="history">تارىخ</string>
+    <string name="reset">ئەسلىگە قايتۇر</string>
+    <string name="imageState">قوللانغان ئۈنۈملەر</string>
+    <string name="compare_original">سېلىشتۇر</string>
+    <string name="apply_effect">قوللان</string>
+    <string name="reset_effect">ئەسلىگە قايتۇر</string>
+    <string name="aspect">ئېگىز-كەڭلىك</string>
+    <string name="aspect1to1_effect">1, 1</string>
+    <string name="aspect4to3_effect">4:3</string>
+    <string name="aspect3to4_effect">3:4</string>
+    <string name="aspect4to6_effect">4:6</string>
+    <string name="aspect5to7_effect">5:7</string>
+    <string name="aspect7to5_effect">7:5</string>
+    <string name="aspect9to16_effect">16:9</string>
+    <string name="aspectNone_effect">يوق</string>
+    <string name="Fixed">مۇقىم</string>
+    <string name="tinyplanet">كىچىك پىلانىت</string>
+    <string name="exposure" msgid="1229093066434614811">نۇر ئۆتۈش</string>
+    <string name="sharpness">ئېنىقلىقى</string>
+    <string name="contrast">ئاق-قارىلىقى</string>
+    <string name="vibrance">تەبىئى تويۇنۇش</string>
+    <string name="saturation">تويۇنۇش</string>
+    <string name="bwfilter">BW سۈزگۈچ</string>
+    <string name="wbalance">ئاپتوماتىك رەڭ</string>
+    <string name="hue">رەڭگى</string>
+    <string name="shadow_recovery">سايە</string>
+    <string name="highlight_recovery">يورۇت</string>
+    <string name="curvesRGB">ئەگرى سىزىقلار</string>
+    <string name="vignette">سايە</string>
+    <string name="vignette_main">سايە</string>
+    <string name="vignette_exposure">نۇر ئۆتۈش</string>
+    <string name="vignette_saturation">تويۇنۇش</string>
+    <string name="vignette_contrast">ئاق-قارىلىقى</string>
+    <string name="vignette_falloff">ئاجىزلىشىشى</string>
+    <string name="redeye">قىزىل كۆز</string>
+    <string name="imageDraw">سىز</string>
+    <string name="straighten" msgid="5217801513491493491">تۈزلە</string>
+    <string name="crop" msgid="5584000454518174632">كەس</string>
+    <string name="rotate" msgid="460017689320955494">ئايلاندۇر</string>
+    <string name="mirror">ئەينەك</string>
+    <string name="negative">تەتۈر رەڭ</string>
+    <string name="none" msgid="3601545724573307541">يوق</string>
+    <string name="edge">گىرۋەكلەر</string>
+    <string name="kmeans">رەڭ تۈسى ئايرىش</string>
+    <string name="downsample">ئاستى مىسال</string>
+    <string name="grad">تەدرىجىي ئۆزگىرىش</string>
+    <string name="editor_grad_brightness">يورۇقلۇق</string>
+    <string name="editor_grad_contrast">ئاق-قارىلىقى</string>
+    <string name="editor_grad_saturation">تويۇنۇش</string>
+    <string name="editor_chan_sat_main">ئاساسىي تىزىملىك</string>
+    <string name="editor_chan_sat_red">قىزىل</string>
+    <string name="editor_chan_sat_yellow">سېرىق</string>
+    <string name="editor_chan_sat_green">يېشىل</string>
+    <string name="editor_chan_sat_cyan">توق يېشىل</string>
+    <string name="editor_chan_sat_blue">كۆك</string>
+    <string name="editor_chan_sat_magenta">ئاچ قىزىل</string>
+    <string name="editor_grad_style">ئۇسلۇب</string>
+    <string name="editor_grad_new">يېڭى</string>
+    <string name="curves_channel_rgb">RGB</string>
+    <string name="curves_channel_red">قىزىل</string>
+    <string name="curves_channel_green">يېشىل</string>
+    <string name="curves_channel_blue">كۆك</string>
+    <string name="draw_style">ئۇسلۇب</string>
+    <string name="draw_size">چوڭلۇقى</string>
+    <string name="draw_hue">رەڭگى</string>
+    <string name="draw_saturation">تويۇنۇش</string>
+    <string name="draw_value">يورۇقلۇق</string>
+    <string name="draw_color">رەڭ</string>
+    <string name="draw_style_line">سىزىقلار</string>
+    <string name="draw_style_brush_spatter">بەلگە قەلىمى</string>
+    <string name="draw_style_brush_marker">چاچقۇن</string>
+    <string name="draw_clear">تازىلا</string>
+    <string name="color_border_size">قېلىنلىقى</string>
+    <string name="color_border_corner_size">بۇلۇڭ چوڭلۇقى</string>
+    <string name="color_border_color">رەڭ</string>
+    <string name="color_border_clear">تازىلا</string>
+    <string name="color_pick_select">ئىختىيارىي رەڭ تاللاڭ</string>
+    <string name="color_pick_title">رەڭ تاللاڭ</string>
+    <string name="draw_size_title">چوڭلۇقىنى تاللاڭ</string>
+    <string name="draw_size_accept">جەزملە</string>
+    <string name="state_panel_original">ئەسلى</string>
+    <string name="state_panel_result">نەتىجە</string>
+    <string name="filtershow_notification_label">سۈرەتنى ساقلاۋاتىدۇ</string>
+    <string name="filtershow_notification_message">بىر تەرەپ قىلىۋاتىدۇ…</string>
+    <string name="filtershow_save_preset">نۆۋەتتى ئالدىن تەڭشەكنى ساقلا</string>
+    <string name="filtershow_manage_preset">ئىشلەتكۈچى ئالدىن تەڭشەكنى باشقۇر</string>
+    <string name="filtershow_new_preset">يېڭى ئالدىن تەڭشەك</string>
+    <string name="filtershow_preset_name">ئالدىن تەڭشەك ئىسمى</string>
+    <string name="filtershow_show_info_panel">ئۇچۇر</string>
+    <string name="filtershow_show_info_panel_name">سۈرەت ئاتى</string>
+    <string name="filtershow_show_info_panel_size">سۈرەت چوڭلۇقى</string>
+    <string name="filtershow_show_info_panel_histogram">چاسا دىئاگرامما</string>
+    <string name="filtershow_show_info_panel_exif">EXIF سانلىق مەلۇمات</string>
+    <string name="filtershow_add_button_looks">ئالدىن تەڭشەك</string>
+    <string name="filtershow_add_button_versions">نەشرى</string>
+    <string name="filtershow_version_original">ئەسلى</string>
+    <string name="filtershow_version_current">نۆۋەتتىكى</string>
+    <string name="filtershow_exif_model">ئەندىزە</string>
+    <string name="filtershow_exif_aperture">نۇر گەردىشى</string>
+    <string name="filtershow_exif_focal_length">فوكۇس ئارىلىقى</string>
+    <string name="filtershow_exif_subject_distance">جىسىم ئارىلىقى</string>
+    <string name="filtershow_exif_date">تارتىلغان چېسلا</string>
+    <string name="filtershow_exif_f_stop">يورۇقلۇق چەمبەر قىممىتى</string>
+    <string name="filtershow_exif_exposure_time">نۇرلاندۇرۇش ۋاقتى</string>
+    <string name="filtershow_exif_copyright">نەشر ھوقوقى</string>
+</resources>
diff --git a/res/values-ug/strings.xml b/res/values-ug/strings.xml
new file mode 100644
index 0000000..5406acb
--- /dev/null
+++ b/res/values-ug/strings.xml
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">سۈرەت يىغقۇچ</string>
+    <string name="gadget_title">رەسىم كاندۇك</string>
+    <string name="movie_view_label">سىن  قويغۇچ</string>
+    <string name="loading_video">سىن يۈكلەۋاتىدۇ…</string>
+    <string name="loading_image">سۈرەت يۈكلەۋاتىدۇ…</string>
+    <string name="loading_account">ھېسابات يۈكلەۋاتىدۇ…</string>
+    <string name="resume_playing_title">سىننى داۋاملاشتۇر</string>
+    <string name="resume_playing_message">%s دىن قويۇشنى داۋاملاشتۇرامدۇ؟</string>
+    <string name="resume_playing_resume">قويۇشنى داۋاملاشتۇر</string>
+    <string name="loading">يۈكلەۋاتىدۇ…</string>
+    <string name="fail_to_load">يۈكلىيەلمىدى</string>
+    <string name="fail_to_load_image">بۇ سۈرەتنى يۈكلىيەلمەيدۇ</string>
+    <string name="no_thumbnail">كىچىك سۈرەت يوق</string>
+    <string name="resume_playing_restart">قايتا باشلا</string>
+    <string name="crop_save_text">جەزملە</string>
+    <string name="ok">جەزملە</string>
+    <string name="multiface_crop_help">چىرايدىن بىرسى چېكىلسە باشلايدۇ.</string>
+    <string name="saving_image">رەسىم ساقلاۋاتىدۇ…</string>
+    <string name="filtershow_saving_image">رەسىمنى <xliff:g id="ALBUM_NAME">%1$s</xliff:g> غا ساقلاۋاتىدۇ…</string>
+    <string name="save_error">كېسىلگەن سۈرەتنى ساقلىيالمايدۇ.</string>
+    <string name="crop_label">رەسىم كەس</string>
+    <string name="trim_label">سىن كەس</string>
+    <string name="select_image">سۈرەت تاللاڭ</string>
+    <string name="select_video">سىن تاللاش</string>
+    <string name="select_item">تۈر تاللاڭ</string>
+    <string name="select_album">ئالبۇم تاللاڭ</string>
+    <string name="select_group">گۇرۇپپا تاللاڭ</string>
+    <string name="set_image">رەسىم تەڭشىكى</string>
+    <string name="set_wallpaper">تام قەغەز تەڭشىكى</string>
+    <string name="wallpaper">تام قەغەز تەڭشەۋاتىدۇ\u2026</string>
+    <string name="camera_setas_wallpaper">تام قەغىزى</string>
+    <string name="delete">ئۆچۈر</string>
+    <string name="confirm">جەزملە</string>
+    <string name="cancel">ۋاز كەچ</string>
+    <string name="share">ھەمبەھىر</string>
+    <string name="share_panorama">پۈتۈن مەنزىرە ھەمبەھىر</string>
+    <string name="share_as_photo">سۈرەت سۈپىتىدە ھەمبەھىر</string>
+    <string name="deleted">ئۆچۈرۈلدى</string>
+    <string name="undo">يېنىۋال</string>
+    <string name="select_all">ھەممىنى تاللا</string>
+    <string name="deselect_all">ھەممىنى تاللىما</string>
+    <string name="slideshow">تام تەسۋىر كۆرسەت</string>
+    <string name="details">تەپسىلاتى</string>
+    <string name="details_title">%2$d دىن %1$d تۈر:</string>
+    <string name="close">ياپ</string>
+    <string name="switch_to_camera">كامېراغا ئالماشتۇر</string>
+    <string name="show_on_map">خەرىتىدە كۆرسەت</string>
+    <string name="rotate_left">سولغا ئايلاندۇر</string>
+    <string name="rotate_right">ئوڭغا ئايلاندۇر</string>
+    <string name="no_such_item">تۈرنى تاپالمىدى.</string>
+    <string name="edit">تەھرىر</string>
+    <string name="simple_edit">ئاددىي تەھرىر</string>
+    <string name="process_caching_requests">غەملەش ئىلتىماسىنى بىر تەرەپ قىلىۋاتىدۇ</string>
+    <string name="caching_label">غەملەۋاتىدۇ…</string>
+    <string name="crop_action">كەس</string>
+    <string name="trim_action">كەس</string>
+    <string name="mute_action">ئۈنسىز</string>
+    <string name="set_as">تەڭشىكى</string>
+    <string name="video_mute_err">سىننى ئۈنسىز قىلالمايدۇ.</string>
+    <string name="video_err">سىننى قويالمايدۇ</string>
+    <string name="group_by_location">ئورنى بويىچە</string>
+    <string name="group_by_time">ۋاقىت بويىچە</string>
+    <string name="group_by_tags">بەلگە بويىچە</string>
+    <string name="group_by_faces">كىشى بويىچە</string>
+    <string name="group_by_album">ئالبۇم بويىچە</string>
+    <string name="group_by_size">چوڭلۇقى بويىچە</string>
+    <string name="untagged">بەلگە قويۇلمىغان</string>
+    <string name="no_location">ئورنى يوق</string>
+    <string name="no_connectivity">بەزى ئورۇنلارنى تور كاشىلىسى سەۋەبىدىن ئېنىقلىيالمىدى.</string>
+    <string name="sync_album_error">بۇ ئالبۇمدىكى سۈرەتلەرنى چۈشۈرەلمىدى. سەل تۇرۇپ قايتا سىناڭ.</string>
+    <string name="show_images_only">سۈرەتلەرلا</string>
+    <string name="show_videos_only">سىنلارلا</string>
+    <string name="show_all">سۈرەت ۋە سىنلار</string>
+    <string name="appwidget_title">سۈرەت يىغقۇچ</string>
+    <string name="appwidget_empty_text">سۈرەت يوق.</string>
+    <string name="crop_saved">كېسىلگەن سۈرەت <xliff:g id="FOLDER_NAME">%s</xliff:g> غا ساقلاندى.</string>
+    <string name="no_albums_alert">ئىشلەتكىلى بولىدىغان ئالبۇم يوق.</string>
+    <string name="empty_album">سۈرەت/سىننى ئىشلەتكىلى بولىدۇ.</string>
+    <string name="picasa_posts">يازمىلار</string>
+    <string name="make_available_offline">تورسىز ئىشلەتكىلى بولىدۇ</string>
+    <string name="sync_picasa_albums">يېڭىلا</string>
+    <string name="done">تامام</string>
+    <string name="sequence_in_set">%2$d دىن %1$d تۈر:</string>
+    <string name="title">ماۋزۇ</string>
+    <string name="description">چۈشەندۈرۈش</string>
+    <string name="time">ۋاقىت</string>
+    <string name="location">ئورنى</string>
+    <string name="path">يول</string>
+    <string name="width">كەڭلىك</string>
+    <string name="height">ئېگىزلىك</string>
+    <string name="orientation">يۆنىلىش</string>
+    <string name="duration">داۋاملىشىش ۋاقتى</string>
+    <string name="mimetype">MIME تىپى</string>
+    <string name="file_size">ھۆججەت چوڭلۇقى</string>
+    <string name="maker">ياسىغۇچ</string>
+    <string name="model">ئەندىزە</string>
+    <string name="flash">چاقماق لامپا</string>
+    <string name="aperture">نۇر گەردىشى</string>
+    <string name="focal_length">فوكۇس ئارىلىقى</string>
+    <string name="white_balance">ئاق تەڭپۇڭلۇق</string>
+    <string name="exposure_time">ئاشكارىلانغان ۋاقتى</string>
+    <string name="manual">قولدا</string>
+    <string name="auto">ئاپتوماتىك</string>
+    <string name="flash_on">چاقماق لامپا</string>
+    <string name="flash_off">چاقماق لامپا يوق</string>
+    <string name="unknown">يوچۇن</string>
+    <string name="ffx_original">ئەسلى</string>
+    <string name="ffx_vintage">قەدىمىي</string>
+    <string name="ffx_instant">شۇئان</string>
+    <string name="ffx_bleach">ئاقارتىش</string>
+    <string name="ffx_blue_crush">كۆك</string>
+    <string name="ffx_bw_contrast">B/W</string>
+    <string name="ffx_punch">يۇيۇپ چىڭداش</string>
+    <string name="ffx_x_process">ئەكسى يۇيۇش</string>
+    <string name="ffx_washout">لاتتې قەھۋە</string>
+    <string name="ffx_washout_color">تاش باسما</string>
+    <string name="try_to_set_local_album_available_offline">بۇ تۈر يەرلىك ئورۇنغا ساقلاندى، تورسىز ئىشلەتكىلى بولىدۇ.</string>
+    <string name="set_label_all_albums">ھەممە ئالبۇم</string>
+    <string name="set_label_local_albums">يەرلىك ئالبۇم</string>
+    <string name="set_label_mtp_devices">MTP ئۈسكۈنىلىرى</string>
+    <string name="set_label_picasa_albums">Picasa ئالبۇمى</string>
+    <string name="free_space_format"><xliff:g id="BYTES">%s</xliff:g> بوش</string>
+    <string name="size_below"><xliff:g id="SIZE">%s</xliff:g> ياكى تۆۋەن</string>
+    <string name="size_above"><xliff:g id="SIZE">%s</xliff:g> ياكى يۇقىرى</string>
+    <string name="size_between"><xliff:g id="MIN_SIZE">%1$s</xliff:g> دىن <xliff:g id="MAX_SIZE">%2$s</xliff:g> غا</string>
+    <string name="Import">ئەكىر</string>
+    <string name="import_complete">ئەكىرىش تامام</string>
+    <string name="import_fail">ئەكىرەلمىدى</string>
+    <string name="camera_connected">كامېرا باغلاندى</string>
+    <string name="camera_disconnected">كامېرا ئۈزۈلدى</string>
+    <string name="click_import">بۇ جاي چېكىلسە ئەكىرىدۇ</string>
+    <string name="widget_type_album">بىر ئالبۇم تاللاڭ</string>
+    <string name="widget_type_shuffle">ھەممە سۈرەتنى سۆرەڭ</string>
+    <string name="widget_type_photo">بىر سۈرەت تاللاڭ:</string>
+    <string name="widget_type">سۈرەت تاللاڭ</string>
+    <string name="slideshow_dream_name">تام تەسۋىر كۆرسەت</string>
+    <string name="albums">سۈرەت توپلىمى</string>
+    <string name="times">ۋاقىت</string>
+    <string name="locations">ئورنى</string>
+    <string name="people">كىشى</string>
+    <string name="tags">خەتكۈچلەر</string>
+    <string name="group_by">گۇرۇپپا ئاساسى</string>
+    <string name="settings">تەڭشەكلەر</string>
+    <string name="add_account">ھېسابات قوش</string>
+    <string name="folder_camera">كامېرا</string>
+    <string name="folder_download">چۈشۈر</string>
+    <string name="folder_edited_online_photos">تەھرىرلەنگەن توردىكى سۈرەتلەر</string>
+    <string name="folder_imported">ئەكىردى</string>
+    <string name="folder_screenshot">ئېكراندىن تۇتۇلغان سۈرەت</string>
+    <string name="help">ياردەم</string>
+    <string name="no_external_storage_title">ساقلىغۇچ يوق</string>
+    <string name="no_external_storage">ھېچقانداق سىرتقى ساقلىغۇچ يوق</string>
+    <string name="switch_photo_filmstrip">تام تەسۋىر كۆرۈنۈش</string>
+    <string name="switch_photo_grid">سېتكا كۆرۈنۈش</string>
+    <string name="switch_photo_fullscreen">پۈتۈن ئېكران كۆرۈنۈش</string>
+    <string name="trimming">كېسىۋاتىدۇ</string>
+    <string name="muting">ئۈنسىز قىلىۋاتىدۇ</string>
+    <string name="please_wait">سەل كۈتۈڭ</string>
+    <string name="save_into">سىننى <xliff:g id="ALBUM_NAME">%1$s</xliff:g> غا ساقلاۋاتىدۇ…</string>
+    <string name="trim_too_short">كېسەلمەيدۇ: نىشان سىن بەك قىسقا\"</string>
+    <string name="pano_progress_text">پۈتۈن مەنزىرە سۈرەتنى رەڭلەۋاتىدۇ</string>
+    <string name="save" msgid="8140440041190264400">ساقلا</string>
+    <string name="ingest_scanning" msgid="2048262851775139720">مەزمۇننى تەكشۈرۈۋاتىدۇ…</string>
+    <string name="ingest_sorting" msgid="624687230903648118">تەرتىپلەۋاتىدۇ…</string>
+    <string name="ingest_scanning_done">تەكشۈرۈش تامام</string>
+    <string name="ingest_importing">ئەكىرىۋاتىدۇ…</string>
+    <string name="ingest_empty_device">بۇ ئۈسكۈنىدە ئەكىرگىلى بولىدىغان ھېچقانداق مەزمۇن يوق.</string>
+    <string name="ingest_no_device">ھېچقانداق MTP ئۈسكۈنە باغلانمىدى</string>
+    <string name="camera_error_title">كامېرا خاتالىقى</string>
+    <string name="cannot_connect_camera">كامېراغا باغلىنالمىدى</string>
+    <string name="camera_disabled">بىخەتەرلىك تەدبىرى سەۋەبىدىن كامېرا چەكلەندى.</string>
+    <string name="camera_label">كامېرا</string>
+    <string name="wait">سەل كۈتۈڭ…</string>
+    <string name="no_storage" product="nosdcard">كامېرانى ئىشلىتىشتىن ئىلگىرى USB ساقلىغۇچنى ئېگەرلەڭ.</string>
+    <string name="no_storage" product="default">كامېرا ئىشلىتىشتىن ئىلگىرى SD كارتا قىستۇرۇڭ.</string>
+    <string name="preparing_sd" product="nosdcard">USB ساقلىغۇچنى تەييارلاۋاتىدۇ…</string>
+    <string name="preparing_sd" product="default">SD كارتا تەييارلاۋاتىدۇ…</string>
+    <string name="access_sd_fail" product="nosdcard">USB ساقلىغۇچنى زىيارەت قىلالمايدۇ.</string>
+    <string name="access_sd_fail" product="default">SD كارتىنى زىيارەت قىلالمايدۇ.</string>
+    <string name="review_cancel">ۋاز كەچ</string>
+    <string name="review_ok">تامام</string>
+    <string name="time_lapse_title">ۋاقىت بەلگىلەپ خاتىرىلەش</string>
+    <string name="pref_camera_id_title">كامېرا تاللاڭ</string>
+    <string name="pref_camera_id_entry_back">قايت</string>
+    <string name="pref_camera_id_entry_front">ئالدى</string>
+    <string name="pref_camera_recordlocation_title">ساقلاش ئورنى</string>
+    <string name="pref_camera_location_label">ئورنى</string>
+    <string name="pref_camera_timer_title">تەتۈر سانىغۇچ ۋاقىت خاتىرىلىگۈچ</string>
+    <string name="pref_camera_timer_sound_title">تەتۈر ساناۋاتقاندا ئەسكەرتىش ئاۋازى چىقار</string>
+    <string name="setting_off">تاقاق</string>
+    <string name="setting_on">ئوچۇق</string>
+    <string name="pref_video_quality_title">سىن سۈپىتى</string>
+    <string name="pref_video_quality_entry_high">يۇقىرى</string>
+    <string name="pref_video_quality_entry_low">تۆۋەن</string>
+    <string name="pref_video_time_lapse_frame_interval_title">ۋاقىت بەلگىلەپ سۈرەت تارتىش</string>
+    <string name="pref_camera_settings_category">كامېرا تەڭشەك</string>
+    <string name="pref_camcorder_settings_category">سىنئالغۇ تەڭشەك</string>
+    <string name="pref_camera_picturesize_title">رەسىم چوڭلۇقى</string>
+    <string name="pref_camera_picturesize_entry_13mp">13 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_8mp">8 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_5mp">5 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_4mp">4 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_3mp">3 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_2mp">2 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_2mp_wide">2 مىليون پىكسېل (16:9)</string>
+    <string name="pref_camera_picturesize_entry_1_3mp">1،3 مىليون پىكسېل</string>
+    <string name="pref_camera_picturesize_entry_1mp">1 مىليون پىكسېل</string>
+    <string name="pref_camera_focusmode_title">فوكۇس مودېلى</string>
+    <string name="pref_camera_focusmode_entry_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_focusmode_entry_infinity">چەكسىز</string>
+    <string name="pref_camera_focusmode_entry_macro">ماكرو</string>
+    <string name="pref_camera_focusmode_label_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_focusmode_label_infinity">چەكسىز</string>
+    <string name="pref_camera_focusmode_label_macro">ماكرو</string>
+    <string name="pref_camera_flashmode_title">قول چىراغ ھالىتى</string>
+    <string name="pref_camera_flashmode_label">چاقماق چىراغ ھالىتى</string>
+    <string name="pref_camera_flashmode_entry_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_flashmode_entry_on">ئوچۇق</string>
+    <string name="pref_camera_flashmode_entry_off">تاقاق</string>
+    <string name="pref_camera_flashmode_label_auto">چاقماق چىراغ ئاپتوماتىل</string>
+    <string name="pref_camera_flashmode_label_on">چاقماق چىراغ ئوچۇق</string>
+    <string name="pref_camera_flashmode_label_off">چاقماق چىراغ تاقاق</string>
+    <string name="pref_camera_whitebalance_title">ئاق تەڭپۇڭلۇق</string>
+    <string name="pref_camera_whitebalance_label">ئاق تەڭپۇڭلۇق</string>
+    <string name="pref_camera_whitebalance_entry_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_whitebalance_entry_incandescent">چوغلانما لامپا</string>
+    <string name="pref_camera_whitebalance_entry_daylight">كۈن نۇرى</string>
+    <string name="pref_camera_whitebalance_entry_fluorescent">يالتىراق لامپا</string>
+    <string name="pref_camera_whitebalance_entry_cloudy">بۇلۇتلۇق</string>
+    <string name="pref_camera_whitebalance_label_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_whitebalance_label_incandescent">چوغلانما لامپا</string>
+    <string name="pref_camera_whitebalance_label_daylight">كۈن نۇرى</string>
+    <string name="pref_camera_whitebalance_label_fluorescent">يالتىراق لامپا</string>
+    <string name="pref_camera_whitebalance_label_cloudy">بۇلۇتلۇق</string>
+    <string name="pref_camera_scenemode_title">مەنزىرە ھالىتى</string>
+    <string name="pref_camera_scenemode_entry_auto">ئاپتوماتىك</string>
+    <string name="pref_camera_scenemode_entry_action">مەشغۇلات</string>
+    <string name="pref_camera_scenemode_entry_night">كېچە</string>
+    <string name="pref_camera_scenemode_entry_sunset">كۈن پېتىش</string>
+    <string name="pref_camera_scenemode_entry_party">يىغىلىش</string>
+    <string name="pref_camera_scenemode_label_auto">يوق</string>
+    <string name="pref_camera_scenemode_label_action">مەشغۇلات</string>
+    <string name="pref_camera_scenemode_label_night">كېچە</string>
+    <string name="pref_camera_scenemode_label_sunset">كۈن پېتىش</string>
+    <string name="pref_camera_scenemode_label_party">يىغىلىش</string>
+    <string name="pref_camera_countdown_label">تەتۈر سانىغۇچ ۋاقىت خاتىرىلىگۈچ</string>
+    <string name="pref_camera_countdown_label_off">ۋاقىت خاتىرىلىگۈچ تاقاق</string>
+    <string name="pref_camera_countdown_label_one">1 سېكۇنت</string>
+    <string name="pref_camera_countdown_label_three">3 سېكۇنت</string>
+    <string name="pref_camera_countdown_label_ten">10 سېكۇنت</string>
+    <string name="pref_camera_countdown_label_fifteen">15 سېكۇنت</string>
+    <string name="not_selectable_in_scene_mode">تەڭشەكنى مەنزىرە ھالىتىدە تاللىغىلى بولمايدۇ.</string>
+    <string name="pref_exposure_title">نۇر ئۆتۈش</string>
+    <string name="pref_exposure_label">نۇر ئۆتۈش</string>
+    <string name="pref_camera_id_label_back">ئالدى كامېرا</string>
+    <string name="pref_camera_id_label_front">كەينى كامېرا</string>
+    <string name="dialog_ok">جەزملە</string>
+    <string name="spaceIsLow_content" product="nosdcard">USB ساقلىغۇچ بوشلۇقىڭىز توشاي دېدى. سۈپەت تەڭشەكنى ئۆزگەرتىڭ ياكى بەزى سۈرەتلەرنى ياكى باشقا ھۆججەتلەرنى ئۆچۈرۈڭ.</string>
+    <string name="spaceIsLow_content" product="default">SD كارتا بوشلۇقىڭىز توشاي دېدى. سۈپەت تەڭشەكنى ئۆزگەرتىڭ ياكى بەزى سۈرەتلەرنى ياكى باشقا ھۆججەتلەرنى ئۆچۈرۈڭ.</string>
+    <string name="video_reach_size_limit">چوڭلۇق چېكىگە يەتتى.</string>
+    <string name="pano_too_fast_prompt">بەك تېز</string>
+    <string name="pano_dialog_prepare_preview">پۈتۈن مەنزىرە تەييارلاۋاتىدۇ</string>
+    <string name="pano_dialog_panorama_failed">پۈتۈن مەنزىرە ساقلىيالمايدۇ.</string>
+    <string name="pano_dialog_title">پۈتۈن مەنزىرە</string>
+    <string name="pano_capture_indication">پۈتۈن مەنزىرە سۈرەت تارتىۋاتىدۇ</string>
+    <string name="pano_dialog_waiting_previous">ئالدىنقى پۈتۈن مەنزىرە سۈرەتنىڭ بىر تەرەپ قىلىنىشىنى كۈتۈۋاتىدۇ</string>
+    <string name="pano_review_saving_indication_str">ساقلاۋاتىدۇ…</string>
+    <string name="pano_review_rendering">پۈتۈن مەنزىرە سۈرەتنى رەڭلەۋاتىدۇ</string>
+    <string name="tap_to_focus">چېكىسلە فوكۇس توغرىلايدۇ.</string>
+    <string name="pref_video_effect_title">ئالاھىدە ئۈنۈم</string>
+    <string name="effect_none">يوق</string>
+    <string name="effect_goofy_face_squeeze">شەيتان ئەينەك</string>
+    <string name="effect_goofy_face_big_eyes">چوڭ كۆز</string>
+    <string name="effect_goofy_face_big_mouth">چوڭ ئېغىز</string>
+    <string name="effect_goofy_face_small_mouth">كىچىك ئېغىز</string>
+    <string name="effect_goofy_face_big_nose">چوڭ بۇرۇن</string>
+    <string name="effect_goofy_face_small_eyes">كىچىك كۆز</string>
+    <string name="effect_backdropper_space">ئالەم تەگلىكى</string>
+    <string name="effect_backdropper_sunset">كۈن پېتىش</string>
+    <string name="effect_backdropper_gallery">سىنلىرىڭىز</string>
+    <string name="bg_replacement_message">ئۈسكۈنىنى پەسكە قويۇڭ.\"\n\"كۆرۈنۈش ئالدىدىن بىر دەم ئايرىلىڭ.</string>
+    <string name="video_snapshot_hint">سىنغا ئېلىۋاتقاندا چېكىلسە بىر پارچە سۈرەت تارتىدۇ.</string>
+    <string name="video_recording_started">سىنغا ئېلىش باشلاندى.</string>
+    <string name="video_recording_stopped">سىنغا ئېلىش توختىدى.</string>
+    <string name="disable_video_snapshot_hint">ئالاھىدە ئۈنۈمنى قوزغاتقاندا سىندىن سۈرەت تۇتۇش چەكلىنىدۇ.</string>
+    <string name="clear_effects">ئۈنۈمنى تازىلا</string>
+    <string name="effect_silly_faces">كۈلكىلىك چىرايلار</string>
+    <string name="effect_background">تەگلىك</string>
+    <string name="accessibility_shutter_button">Shutter توپچا</string>
+    <string name="accessibility_menu_button">تىزىملىك توپچا</string>
+    <string name="accessibility_review_thumbnail">يېقىنقى سۈرەت</string>
+    <string name="accessibility_camera_picker">ئالدى كەينى كامېرا ئالماشتۇرغۇچ</string>
+    <string name="accessibility_mode_picker">كامېرا، سىن ياكى پۈتۈن مەنزىرە تاللىغۇچ</string>
+    <string name="accessibility_second_level_indicators">تېخىمۇ كۆپ تەڭشەك تىزگىنلىرى</string>
+    <string name="accessibility_back_to_first_level">تەڭشەك تىزگىنىنى ياپ</string>
+    <string name="accessibility_zoom_control">يىراق يېقىن  تىزگىنى</string>
+    <string name="accessibility_decrement">%1$s نى يىراقلات</string>
+    <string name="accessibility_increment">%1$s نى يېقىنلات</string>
+    <string name="accessibility_check_box">%1$s كۆپ تاللاش رامكىسى</string>
+    <string name="accessibility_switch_to_camera">سۈرەتكە ئالماشتۇر</string>
+    <string name="accessibility_switch_to_video">سىنغا ئالماشتۇر</string>
+    <string name="accessibility_switch_to_panorama">پۈتۈن مەنزىرىگە ئالماشتۇر</string>
+    <string name="accessibility_switch_to_new_panorama">يېڭى پۈتۈن مەنزىرىگە ئالماشتۇر</string>
+    <string name="accessibility_switch_to_refocus">قايتا فوكۇسلاشقا ئالماشتۇر</string>
+    <string name="accessibility_review_cancel">ئالدىن كۆزىتىشتىن ۋاز كەچ</string>
+    <string name="accessibility_review_ok">ئالدىن كۆزىتىش تامام</string>
+    <string name="accessibility_review_retake">ئالدىن كۆزىتىشنى قايتا تارت</string>
+    <string name="accessibility_play_video">سىن چال</string>
+    <string name="accessibility_pause_video">سىننى ۋاقىتلىق توختات</string>
+    <string name="accessibility_reload_video">سىننى قايتا يۈكلە</string>
+    <string name="accessibility_time_bar">سىن چالغۇچ ۋاقىت بالداق</string>
+    <string name="capital_on">ئوچۇق</string>
+    <string name="capital_off">تاقاق</string>
+    <string name="pref_video_time_lapse_frame_interval_off">تاقاق</string>
+    <string name="pref_video_time_lapse_frame_interval_500">0.5 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_1000">1 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_1500">1.5 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_2000">2 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_2500">2.5 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_3000">3 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_4000">4 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_5000">5 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_6000">6 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_10000">10 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_12000">12 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_15000">15 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_24000">24 سېكۇنت</string>
+    <string name="pref_video_time_lapse_frame_interval_30000">0-5 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_60000">1 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_90000">1.5 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_120000">2 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_150000">2.5 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_180000">3 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_240000">4 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_300000">5 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_360000">6 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_600000">10 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_720000">12 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_900000">15 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_1440000">24 مىنۇت</string>
+    <string name="pref_video_time_lapse_frame_interval_1800000">0.5 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_3600000">1 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_5400000">1.5 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_7200000">2 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_9000000">2.5 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_10800000">3 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_14400000">4 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_18000000">5 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_21600000">6 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_36000000">10 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_43200000">12 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_54000000">15 سائەت</string>
+    <string name="pref_video_time_lapse_frame_interval_86400000">24 سائەت</string>
+    <string name="time_lapse_seconds">سېكۇنت</string>
+    <string name="time_lapse_minutes">مىنۇت</string>
+    <string name="time_lapse_hours">سائەت</string>
+    <string name="time_lapse_interval_set">تامام</string>
+    <string name="set_time_interval">\"ۋاقىت ئارىلىق تەڭشىكى\"</string>
+    <string name="set_time_interval_help">ۋاقىت كېچىكتۈرۈپ سۈرەت تارتىش ئىقتىدارى تاقالدى. ۋاقىت ئارىلىقى تەڭشىمەكچى بولغاندا، ئالدى بىلەن شۇ ئىقتىدارنى ئېچىڭ.</string>
+    <string name="set_timer_help">تەتۈر ساناق ۋاقىت خاتىرىلىغۇچ تاقاق. سۈرەت تارتىشتىن ئىلگىرى تەتۈر ساناق ئۈچۈن، ئالدى بىلەن شۇ ئىقتىدارنى ئېچىڭ.</string>
+    <string name="set_duration">داۋاملىشىش ۋاقىت تەڭشىكى سېكۇنت</string>
+    <string name="count_down_title_text">سۈرەت تارتىش تەتۈر ساناق ساناۋاتىدۇ</string>
+    <string name="remember_location_title">سۈرەت تارتقان ئورۇننى ئەستە تۇتامدۇ؟</string>
+    <string name="remember_location_prompt">سىز تارتقان سىن ۋە سۈرەتلىرىڭىزگە تارتقان ئورۇن بەلگىسىنى سالىدۇ.\"\n\n\"باشقا ئەپلەر سىز ساقلىغان سۈرەتلەرنى كۆرگەندە بۇ ئۇچۇرلارنى زىيارەت قىلالايدۇ.</string>
+    <string name="remember_location_no">ياق، رەھمەت</string>
+    <string name="remember_location_yes">ھەئە</string>
+    <string name="menu_camera">كامېرا</string>
+    <string name="menu_search">ئىزدە</string>
+    <string name="tab_photos">سۈرەتلەر</string>
+    <string name="tab_albums">سۈرەت توپلىمى</string>
+    <string name="camera_menu_more_label">تېخىمۇ كۆپ تاللانما</string>
+    <string name="camera_menu_settings_label">تەڭشەكلەر</string>
+</resources>
diff --git a/res/values-uk/cm_strings.xml b/res/values-uk/cm_strings.xml
new file mode 100644
index 0000000..67d0911
--- /dev/null
+++ b/res/values-uk/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Час запису</string>
+</resources>
diff --git a/res/values-uk/codeaurora_strings.xml b/res/values-uk/codeaurora_strings.xml
new file mode 100644
index 0000000..f973eb7
--- /dev/null
+++ b/res/values-uk/codeaurora_strings.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Крок</string>
+    <string name="step_option_desc">Налаштувати швидкий крок вперед/назад</string>
+    <string name="setp_option_three_second">3 секунди</string>
+    <string name="setp_option_six_second">6 секунд</string>
+    <string name="loop">"Петля"</string>
+    <string name="single">"Одиночна"</string>
+    <string name="stereo">"Стерео"</string>
+    <string name="speaker_on">Динамік УВІМК</string>
+    <string name="speaker_off">Динамік ВИМК</string>
+    <string name="speaker_need_headset">Підключіть навушники для використання цієї функції.</string>
+    <string name="single_track">"Одна композиція"</string>
+    <string name="input_url">"Введіть URL-адресу"</string>
+    <string name="streaming_settings">"Налаштування трансляції"</string>
+    <string name="next">"Наступна"</string>
+    <string name="previous">"Попередня"</string>
+    <string name="buffer_size">Розмір буфера</string>
+    <string name="apn">Бажаний APN</string>
+    <string name="rtp_min_port">Мін порт</string>
+    <string name="rtp_max_port">Макс порт</string>
+    <string name="set_rtp_min_port">Встановити мін. порт</string>
+    <string name="set_rtp_max_port">Встановити макс. порт</string>
+    <string name="set_buffer_size">Встановити розмір буфера</string>
+    <string name="set_apn">Виберіть бажаний APN</string>
+    <string name="setting">Налаштування</string>
+    <string name="server_timeout_title">"Час очікування сервера"</string>
+    <string name="server_timeout_message">"Підключатися до сервера повторно, щоб відтворити відео?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Не вдалося підключитися, спроба встановити підключення з %1$d\u2026"</string>
+    <string name="media_controller_live">Наживо</string>
+    <string name="media_controller_playing">Відтворюється</string>
+    <string name="media_controller_connecting">Підключення\u2026</string>
+    <string name="bookmark_add">"Додати закладку"</string>
+    <string name="bookmark_display">"Показати закладки"</string>
+    <string name="bookmark_empty">"Немає закладок"</string>
+    <string name="bookmark_exist">"Закладка вже існує"</string>
+    <string name="bookmark_add_success">"Закладку додано"</string>
+    <string name="bookmark_list">"Закладки"</string>
+    <string name="bookmark_title">"Назва"</string>
+    <string name="bookmark_location">"Місцезнаходження"</string>
+    <string name="delete_all">"Видалити все"</string>
+    <string name="default_title">"Назва за замовчуванням"</string>
+    <string name="more_image">Більше зображень</string>
+    <string name="mute_nosupport">Не можна вимкнути звук: відео не підтримується</string>
+    <string name="map_activity_not_found_err">Не встановлено жодних програм з картами, щоб показати місце.</string>
+    <string name="cannot_share_items">Максимальна к-сть вибраних елементів становить 300</string>
+    <string name="share_dialogue_title">Поділитися через</string>
+    <string name="no_faces">Немає обличчя</string>
+    <string name="fail_trim">Даний відеофайл не може бути обрізаний</string>
+    <string name="can_not_trim">Тільки mp4 і 3gp файли можуть бути обрізані</string>
+    <string name="drm_license_info">Відомості про ліцензію DRM</string>
+    <string name="timeline_title">Часова шкала</string>
+    <string name="albums_title">Альбоми</string>
+    <string name="videos_title">Відео</string>
+    <string name="action_viewtype_list">У вигляді списку</string>
+    <string name="tvEmptyAlbum">Фотографії не знайдено</string>
+    <string name="tvEmptyVideos">Відео не знайдені</string>
+    <string name="text_makeup_whiten">Відбілити</string>
+    <string name="text_makeup_Soften">Пом\'якшити</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Великі очі</string>
+    <string name="truescanner_normal">Звичайний</string>
+    <string name="truescanner_white">Біла дошка</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Прибрати відблиски</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">Дивитися прямо</string>
+    <string name="seestraight_input_image_is_small">Введене зображення замале для обробки.</string>
+    <string name="seestraight_process_fail">Не вдалося обробити зображення.</string>
+    <string name="trim_video_exit_title">Скасувати зміни?</string>
+    <string name="trim_video_exit_msg">Скасувати зміни, внесені до цього відео?</string>
+    <string name="trim_video_exit_discard">СКАСУВАТИ</string>
+</resources>
diff --git a/res/values-vi/cm_strings.xml b/res/values-vi/cm_strings.xml
new file mode 100644
index 0000000..93a440f
--- /dev/null
+++ b/res/values-vi/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">Thời gian ghi</string>
+</resources>
diff --git a/res/values-vi/codeaurora_strings.xml b/res/values-vi/codeaurora_strings.xml
new file mode 100644
index 0000000..b31dd16
--- /dev/null
+++ b/res/values-vi/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">Bước</string>
+    <string name="step_option_desc">Tuỳ chỉnh bước tới/lui nhanh</string>
+    <string name="setp_option_three_second">3 giây</string>
+    <string name="setp_option_six_second">16 giây</string>
+    <string name="loop">"Lặp lại"</string>
+    <string name="single">"Đơn"</string>
+    <string name="stereo">"Âm thanh nổi"</string>
+    <string name="speaker_on">Loa ngoài BẬT</string>
+    <string name="speaker_off">Loa ngoài TẮT</string>
+    <string name="speaker_need_headset">Cắm tai nghe để dùng tính năng này.</string>
+    <string name="single_track">"Một bài hát"</string>
+    <string name="input_url">"Nhập URL"</string>
+    <string name="streaming_settings">"Cài đặt phát trực tuyến"</string>
+    <string name="next">"Tiếp theo"</string>
+    <string name="previous">"Trước"</string>
+    <string name="buffer_size">Kích cỡ bộ đệm</string>
+    <string name="apn">APN ưu tiên</string>
+    <string name="rtp_min_port">Cổng nhỏ nhất</string>
+    <string name="rtp_max_port">Cổng lớn nhất</string>
+    <string name="set_rtp_min_port">Đặt cổng nhỏ nhất</string>
+    <string name="set_rtp_max_port">Đặt cổng lớn nhất</string>
+    <string name="set_buffer_size">Đặt kích thước bộ đệm</string>
+    <string name="set_apn">Chọn APN ưu tiên</string>
+    <string name="setting">Cài đặt</string>
+    <string name="server_timeout_title">"Thời gian chờ máy chủ"</string>
+    <string name="server_timeout_message">"Kết nối lại đến máy chủ để phát video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Kết nối thất bại, đang thử kết nối lại đến %1$d\u2026"</string>
+    <string name="media_controller_live">Trực tiếp</string>
+    <string name="media_controller_playing">Đang phát</string>
+    <string name="media_controller_connecting">Đang kết nối\u2026</string>
+    <string name="bookmark_add">"Thêm dấu trang"</string>
+    <string name="bookmark_display">"Hiện dấu trang"</string>
+    <string name="bookmark_empty">"Không có dấu trang"</string>
+    <string name="bookmark_exist">"Dấu trang đã tồn tại"</string>
+    <string name="bookmark_add_success">"Đã thêm dấu trang"</string>
+    <string name="bookmark_list">"Dấu trang"</string>
+    <string name="bookmark_title">"Tiêu đề"</string>
+    <string name="bookmark_location">"Vị trí"</string>
+    <string name="delete_all">"Xoá tất cả"</string>
+    <string name="default_title">"Tiêu đề mặc định"</string>
+    <string name="more_image">Nhiều ảnh hơn</string>
+    <string name="mute_nosupport">Không thể ngắt tiếng: video không hỗ trợ</string>
+    <string name="map_activity_not_found_err">Không có ứng dụng bản đồ để hiện vị trí.</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d video</item>
+    </plurals>
+    <string name="cannot_share_items">Các mục đã chọn lớn nhất cho chia sẻ là 300</string>
+    <string name="share_dialogue_title">Chia sẻ qua</string>
+    <string name="no_faces">Không có khuôn mặt</string>
+    <string name="fail_trim">Xin lỗi, không thể cắt video này</string>
+    <string name="can_not_trim">Chỉ tập tin mp4 và 3gp có thể cắt được</string>
+    <string name="drm_license_info">Thông tin giấy phép DRM</string>
+    <string name="timeline_title">Dòng thời gian</string>
+    <string name="albums_title">Album</string>
+    <string name="videos_title">Video</string>
+    <string name="action_viewtype_list">Chế độ xem danh sách</string>
+    <string name="tvEmptyAlbum">Không tìm thấy hình ảnh</string>
+    <string name="tvEmptyVideos">Không tìm thấy video</string>
+    <string name="text_makeup_whiten">Làm trắng</string>
+    <string name="text_makeup_Soften">Làm mềm</string>
+    <string name="text_makeup_trimface">Gọt mặt</string>
+    <string name="text_makeup_bigeye">Mắt lớn</string>
+    <string name="truescanner_normal">Bình thường</string>
+    <string name="truescanner_white">Bảng trắng</string>
+    <string name="truescanner">Máy quét thực sự</string>
+    <string name="truescanner_remove_glare">Loại bỏ ánh sáng chói</string>
+    <string name="hazebuster_acts">Bộ lọc Đám mây, Sương mù</string>
+    <string name="seestraight_acts">Xem thẳng</string>
+    <string name="seestraight_input_image_is_small">Hình ảnh đầu vào quá nhỏ để xử lý.</string>
+    <string name="seestraight_process_fail">Không thể xử lý hình ảnh.</string>
+    <string name="trim_video_exit_title">Hủy bỏ các thay đổi?</string>
+    <string name="trim_video_exit_msg">Hủy bỏ các thay đổi được thực hiện cho video này?</string>
+    <string name="trim_video_exit_discard">HỦY BỎ</string>
+</resources>
diff --git a/res/values-zh-rCN/cm_strings.xml b/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 0000000..1ab52e1
--- /dev/null
+++ b/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">已记录时间</string>
+</resources>
diff --git a/res/values-zh-rCN/codeaurora_strings.xml b/res/values-zh-rCN/codeaurora_strings.xml
new file mode 100644
index 0000000..da26a0c
--- /dev/null
+++ b/res/values-zh-rCN/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">步长</string>
+    <string name="step_option_desc">自定义快进/倒带步长</string>
+    <string name="setp_option_three_second">3 秒</string>
+    <string name="setp_option_six_second">6 秒</string>
+    <string name="loop">"循环"</string>
+    <string name="single">"单声道"</string>
+    <string name="stereo">"立体声​​​"</string>
+    <string name="speaker_on">扬声器 开</string>
+    <string name="speaker_off">扬声器 关</string>
+    <string name="speaker_need_headset">插入耳机以使用此功能。</string>
+    <string name="single_track">"单音轨"</string>
+    <string name="input_url">"输入网址"</string>
+    <string name="streaming_settings">"流媒体设置"</string>
+    <string name="next">"下一个"</string>
+    <string name="previous">"上一个"</string>
+    <string name="buffer_size">缓冲大小</string>
+    <string name="apn">首选 APN</string>
+    <string name="rtp_min_port">最小端口</string>
+    <string name="rtp_max_port">最大端口</string>
+    <string name="set_rtp_min_port">设置最小端口</string>
+    <string name="set_rtp_max_port">设置最大端口</string>
+    <string name="set_buffer_size">设置缓冲区大小</string>
+    <string name="set_apn">选择首选的 APN</string>
+    <string name="setting">设置</string>
+    <string name="server_timeout_title">"服务器超时"</string>
+    <string name="server_timeout_message">"重新连接到服务器以便继续播放视频?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"连接失败,正在尝试重新连接到 %1$d\u2026"</string>
+    <string name="media_controller_live">直播</string>
+    <string name="media_controller_playing">正在播放</string>
+    <string name="media_controller_connecting">正在连接\u2026</string>
+    <string name="bookmark_add">"添加书签"</string>
+    <string name="bookmark_display">"显示书签"</string>
+    <string name="bookmark_empty">"没有书签"</string>
+    <string name="bookmark_exist">"书签已存在"</string>
+    <string name="bookmark_add_success">"书签已添加"</string>
+    <string name="bookmark_list">"书签"</string>
+    <string name="bookmark_title">"标题"</string>
+    <string name="bookmark_location">"位置"</string>
+    <string name="delete_all">"删除所有"</string>
+    <string name="default_title">"默认标题"</string>
+    <string name="more_image">更多图片</string>
+    <string name="mute_nosupport">不能静音:视频不支持</string>
+    <string name="map_activity_not_found_err">找不到用于显示地点的地图应用。</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d 个视频</item>
+    </plurals>
+    <string name="cannot_share_items">最多分享 300 项</string>
+    <string name="share_dialogue_title">分享方式</string>
+    <string name="no_faces">无头像</string>
+    <string name="fail_trim">抱歉,此视频文件不能被修剪</string>
+    <string name="can_not_trim">只能修剪 mp4 和 3gp 格式的文件</string>
+    <string name="drm_license_info">DRM 许可证信息</string>
+    <string name="timeline_title">时间线</string>
+    <string name="albums_title">相册</string>
+    <string name="videos_title">视频</string>
+    <string name="action_viewtype_list">列表视图</string>
+    <string name="tvEmptyAlbum">没有找到照片</string>
+    <string name="tvEmptyVideos">没有找到视频</string>
+    <string name="text_makeup_whiten">美白</string>
+    <string name="text_makeup_Soften">磨皮</string>
+    <string name="text_makeup_trimface">瘦脸</string>
+    <string name="text_makeup_bigeye">大眼</string>
+    <string name="truescanner_normal">普通</string>
+    <string name="truescanner_white">白板</string>
+    <string name="truescanner">真实扫描仪</string>
+    <string name="truescanner_remove_glare">清除眩光</string>
+    <string name="hazebuster_acts">雾霾克星</string>
+    <string name="seestraight_acts">看清楚</string>
+    <string name="seestraight_input_image_is_small">输入的图像太小,无法处理。</string>
+    <string name="seestraight_process_fail">无法加载此图像。</string>
+    <string name="trim_video_exit_title">放弃更改?</string>
+    <string name="trim_video_exit_msg">放弃对此视频的更改?</string>
+    <string name="trim_video_exit_discard">放弃</string>
+</resources>
diff --git a/res/values-zh-rHK/codeaurora_strings.xml b/res/values-zh-rHK/codeaurora_strings.xml
new file mode 100644
index 0000000..91dfe8c
--- /dev/null
+++ b/res/values-zh-rHK/codeaurora_strings.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">步驟</string>
+    <string name="step_option_desc">自訂快進/後退步驟</string>
+    <string name="setp_option_six_second">6 秒</string>
+    <string name="loop">"循環"</string>
+    <string name="single">"單聲道"</string>
+    <string name="stereo">"立體聲"</string>
+    <string name="speaker_on">開啟喇叭</string>
+    <string name="speaker_off">關閉喇叭</string>
+    <string name="speaker_need_headset">插上耳機才能使用此功能。</string>
+    <string name="single_track">"單音軌"</string>
+    <string name="input_url">"輸入 URL"</string>
+    <string name="streaming_settings">"串流設定"</string>
+    <string name="next">"下一首"</string>
+    <string name="previous">"上一首"</string>
+    <string name="buffer_size">緩衝區大小</string>
+    <string name="apn">首選 APN</string>
+    <string name="rtp_min_port">最小埠</string>
+    <string name="rtp_max_port">最大埠</string>
+    <string name="set_rtp_min_port">設定最小埠</string>
+    <string name="set_rtp_max_port">設定最大埠</string>
+    <string name="set_buffer_size">設定緩衝區大小</string>
+    <string name="set_apn">選擇首選 APN</string>
+    <string name="setting">設定</string>
+    <string name="server_timeout_title">"伺服器逾時"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"連綫失敗,嘗試重新連綫至 %1$d\u2026"</string>
+    <string name="media_controller_live">直播</string>
+    <string name="media_controller_playing">正在播放</string>
+    <string name="media_controller_connecting">正在連綫\u2026</string>
+    <string name="bookmark_add">"新增書籤"</string>
+    <string name="bookmark_display">"顯示書籤"</string>
+    <string name="bookmark_empty">"無書籤"</string>
+    <string name="bookmark_exist">"書籤已存在"</string>
+    <string name="bookmark_add_success">"書籤已新增"</string>
+    <string name="bookmark_list">"書籤"</string>
+    <string name="bookmark_title">"標題"</string>
+    <string name="bookmark_location">"位置"</string>
+    <string name="delete_all">"全部刪除"</string>
+    <string name="default_title">"預設標題"</string>
+    <string name="more_image">更多圖像</string>
+    <string name="mute_nosupport">無法靜音:影片不支援</string>
+    <string name="map_activity_not_found_err">沒有安裝地圖應用程式供顯示位置。</string>
+    <string name="fail_trim">抱歉,此影片檔無法被修剪</string>
+</resources>
diff --git a/res/values-zh-rTW/cm_strings.xml b/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 0000000..911af7b
--- /dev/null
+++ b/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name="record_time">記錄時間</string>
+</resources>
diff --git a/res/values-zh-rTW/codeaurora_strings.xml b/res/values-zh-rTW/codeaurora_strings.xml
new file mode 100644
index 0000000..606ca91
--- /dev/null
+++ b/res/values-zh-rTW/codeaurora_strings.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="setp_option_name">步驟</string>
+    <string name="step_option_desc">自訂快進/快退步驟</string>
+    <string name="setp_option_three_second">3 秒</string>
+    <string name="setp_option_six_second">6 秒</string>
+    <string name="loop">"重複"</string>
+    <string name="single">"單次"</string>
+    <string name="stereo">"立體聲"</string>
+    <string name="speaker_on">開啟揚聲器</string>
+    <string name="speaker_off">關閉揚聲器</string>
+    <string name="speaker_need_headset">插上耳機即可使用此功能。</string>
+    <string name="single_track">"單音軌"</string>
+    <string name="input_url">"輸入網址"</string>
+    <string name="streaming_settings">"串流媒體設定"</string>
+    <string name="next">"下一首"</string>
+    <string name="previous">"上一首"</string>
+    <string name="buffer_size">緩衝區大小</string>
+    <string name="apn">偏好 APN</string>
+    <string name="rtp_min_port">最小埠</string>
+    <string name="rtp_max_port">最大埠</string>
+    <string name="set_rtp_min_port">設定最小埠</string>
+    <string name="set_rtp_max_port">設定最大埠</string>
+    <string name="set_buffer_size">設定緩衝區大小</string>
+    <string name="set_apn">選擇偏好 APN</string>
+    <string name="setting">設定</string>
+    <string name="server_timeout_title">"伺服器逾時"</string>
+    <string name="server_timeout_message">"重新連線至伺服器並繼續播放影片嗎?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"連線失敗,嘗試重新連線至「%1$d」\u2026"</string>
+    <string name="media_controller_live">直播</string>
+    <string name="media_controller_playing">播放中</string>
+    <string name="media_controller_connecting">連線中\u2026</string>
+    <string name="bookmark_add">"新增書籤"</string>
+    <string name="bookmark_display">"顯示書籤"</string>
+    <string name="bookmark_empty">"沒有書籤"</string>
+    <string name="bookmark_exist">"書籤已存在"</string>
+    <string name="bookmark_add_success">"已新增書籤"</string>
+    <string name="bookmark_list">"書籤"</string>
+    <string name="bookmark_title">"標題"</string>
+    <string name="bookmark_location">"位置"</string>
+    <string name="delete_all">"刪除全部"</string>
+    <string name="default_title">"預設標題"</string>
+    <string name="more_image">更多圖片</string>
+    <string name="mute_nosupport">無法靜音:影片不支援</string>
+    <string name="map_activity_not_found_err">無地圖應用程式可顯示位置</string>
+    <plurals name="number_of_videos">
+        <item quantity="other">%1$d 個影片</item>
+    </plurals>
+    <string name="cannot_share_items">分享的最大選擇項目為 300</string>
+    <string name="share_dialogue_title">分享方式:</string>
+    <string name="no_faces">無人物資訊</string>
+    <string name="fail_trim">抱歉,此影片檔案無法被剪輯</string>
+    <string name="can_not_trim">只有 mp4 和 3gp 檔案才可修剪</string>
+    <string name="drm_license_info">DRM 許可資訊</string>
+    <string name="timeline_title">時間軸</string>
+    <string name="albums_title">相簿</string>
+    <string name="videos_title">影片</string>
+    <string name="action_viewtype_list">清單檢視</string>
+    <string name="tvEmptyAlbum">未找到相片</string>
+    <string name="tvEmptyVideos">未找到影片</string>
+    <string name="text_makeup_whiten">美白</string>
+    <string name="text_makeup_Soften">柔和</string>
+    <string name="text_makeup_trimface">修飾臉部</string>
+    <string name="text_makeup_bigeye">大眼睛</string>
+    <string name="truescanner_normal">適中</string>
+    <string name="truescanner_white">白板</string>
+    <string name="truescanner">即時掃描</string>
+    <string name="truescanner_remove_glare">刪除眩光</string>
+    <string name="hazebuster_acts">霧霾克星</string>
+    <string name="seestraight_acts">看清楚</string>
+    <string name="seestraight_input_image_is_small">輸入圖片太小,無法處理。</string>
+    <string name="seestraight_process_fail">無法處理圖片。</string>
+    <string name="trim_video_exit_title">捨棄變更?</string>
+    <string name="trim_video_exit_msg">捨棄對此影片所做的變更?</string>
+    <string name="trim_video_exit_discard">捨棄</string>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 5a00a69..7dde021 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -14,16 +14,11 @@
      limitations under the License.
 -->
 <resources>
-    <declare-styleable name="Theme.GalleryBase">
-        <attr name="listPreferredItemHeightSmall" format="dimension" />
-        <attr name="switchStyle" format="reference" />
-    </declare-styleable>
+    <declare-styleable name="Theme.GalleryBase"/>
 
     <!-- Camera resources below -->
 
-    <declare-styleable name="CameraPreference">
-        <attr name="title" format="string" />
-    </declare-styleable>
+    <declare-styleable name="CameraPreference"/>
     <declare-styleable name="ListPreference">
         <attr name="key" format="string" />
         <attr name="defaultValue" format="string|reference" />
@@ -42,5 +37,7 @@
         <attr name="largeIcons" format="reference" />
         <attr name="images" format="reference" />
     </declare-styleable>
-
+    <declare-styleable name="FillColor">
+        <attr name="fillColorSelector" format="color" />
+    </declare-styleable>
 </resources>
diff --git a/res/values/bool.xml b/res/values/bool.xml
old mode 100644
new mode 100755
index 464842a..947ed1e
--- a/res/values/bool.xml
+++ b/res/values/bool.xml
@@ -15,4 +15,10 @@
 -->
 <resources>
     <bool name="show_action_bar_title">false</bool>
-</resources>
\ No newline at end of file
+    <bool name="playlist">true</bool>
+    <bool name="loop">true</bool>
+    <bool name="stereo">true</bool>
+    <bool name="streaming">true</bool>
+    <bool name="speaker">true</bool>
+    <bool name="picker_is_dialog">false</bool>
+</resources>
diff --git a/res/values/cm_colors.xml b/res/values/cm_colors.xml
new file mode 100644
index 0000000..4eb65ae
--- /dev/null
+++ b/res/values/cm_colors.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+
+    <color name="primary">#333333</color>
+    <color name="primaryDark">#000000</color>
+    <color name="accent">#33b5e5</color>
+
+    <color name="white">#fafafa</color>
+    <color name="black">#212121</color>
+
+    <color name="light_black">#424242</color>
+
+    <color name="tab_1">@color/primary</color>
+    <color name="tab_2">@color/primary</color>
+    <color name="tab_3">@color/primary</color>
+    <color name="tab_icon_1">@color/white</color>
+    <color name="tab_icon_2">@color/white</color>
+    <color name="tab_icon_3">@color/white</color>
+
+    <color name="black_transparent_1">#1a000000</color>
+    <color name="black_transparent_2">#26000000</color>
+    <color name="black_transparent_3">#75000000</color>
+    <color name="black_transparent_4">#8A000000</color>
+    <color name="black_transparent_5">#C1000000</color>
+</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
new file mode 100644
index 0000000..d6da3b1
--- /dev/null
+++ b/res/values/cm_strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2012-2014 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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">
+    <!-- Text indicating the time a media item was recorded in details window [CHAR LIMIT=14] -->
+    <string name="record_time">Record time</string>
+</resources>
\ No newline at end of file
diff --git a/res/values/codeaurora_filtershow_strings.xml b/res/values/codeaurora_filtershow_strings.xml
new file mode 100644
index 0000000..2244a87
--- /dev/null
+++ b/res/values/codeaurora_filtershow_strings.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!--  Text for filters that apply a frame to a picture [CHAR LIMIT=20] -->
+    <string name="frame">Frame <xliff:g id="number" example="1">%d</xliff:g></string>
+
+    <!--  String displayed when exiting with unsaved changes [CHAR LIMIT=NONE] -->
+    <string name="discard_message">Discard the changes you\'ve made to this image?</string>
+    <!--  String displayed when exiting with unsaved changes [CHAR LIMIT=NONE] -->
+    <string name="discard_title">Discard changes?</string>
+    <!--  String displayed when discard editor [CHAR LIMIT=NONE] -->
+    <string name="discard">Discard</string>
+
+    <!--  Text for the history panel reset button [CHAR LIMIT=20]-->
+    <string name="back_to_original">Back to original</string>
+
+    <!--  Label for the aspect None effect [CHAR LIMIT=15] -->
+    <string name="aspectFree_effect">Free</string>
+
+    <!--  Filters buttons -->
+
+    <!--  True Effect button -->
+    <string name="trueScanner" translatable="false">TrueScanner</string>
+    <!--  HazeBuster button -->
+    <string name="hazeBuster" translatable="false">HazeBuster</string>
+    <!--  SeeStraight button -->
+    <string name="seeStraight" translatable="false">SeeStraight</string>
+
+    <!--  Label for the "refocus" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="focus">Focus</string>
+    <!--  Label for the "fusion" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="fusion">Fusion</string>
+    <!--  Label for the "sketch" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="sketch">Sketch</string>
+    <!--  Label for the "halo" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="halo">Halo</string>
+    <!--  Label for the "zoom" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="zoom">Zoom</string>
+    <!--  Label for the "motion" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="motion">Motion</string>
+    <!--  Label for the "bw" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="bw">B/W</string>
+    <!--  Label for the "blackboard" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="blackboard">Blackboard</string>
+    <!--  Label for the "whiteboard" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="whiteboard">Whiteboard</string>
+    <!--  Label for the "posterize" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="posterize">Posterize</string>
+    <!--  Label for the "negative" dual camera effect  [CHAR LIMIT=15] -->
+    <string name="dc_negative">Negative</string>
+    <!--  Label for the "blur" true portrait effect  [CHAR LIMIT=15] -->
+    <string name="blur">Blur</string>
+    <!--  Label for the "motion blur" true portrait effect  [CHAR LIMIT=15] -->
+    <string name="motion_blur">Motion blur</string>
+
+    <string name="fusion_pick_point">Pick segment</string>
+    <string name="fusion_pick_underlay">Pick underlay</string>
+    <string name="dual_camera_effects">Dual camera effects</string>
+    <string name="dual_camera_effects_intro">Allows you to apply background effects, such as "Motion" and "Sketch". You can also merge two photos together for interesting effects. This feature works best when you have a short distance your camera and the main subject of you picture.</string>
+    <string name="dualcam_no_segment_toast">No segment found at this point</string>
+    <string name="dualcam_filter_not_supported">Dual camera filters not supported for this image</string>
+    <string name="trueportrait_intro">Allows you to enhance photos of people. You can apply effects to the background, such as "Blur" and "Sketch". You can also merge two photos together to create interesting backgrounds for your portrait photos.</string>
+    <string name="trueportrait_no_face">TruePortrait effects cannot be applied to this photo. Face not detected.</string>
+    <string name="trueportrait_edit_intro">With the touch-up tool, you can edit the foreground and the background. You can use your finger to paint in any areas of the foreground or background that were missed.</string>
+    <string name="trueportrait_edit_foreground_toast">Use your finger to paint in any areas of the foreground that were missed.</string>
+    <string name="trueportrait_edit_background_toast">Use your finger to paint in any areas of the background that were missed.</string>
+    <string name="trueportrait_edit_help">To zoom, use two fingers to pinch. You can also drag with two fingers to re-position the image. This can make it easier to fix any problematic areas.</string>
+    <string name="trueportrait_fusion_intro">Your foreground person can be copied and pasted onto any photo in your Gallery. You can try using different background photos to create new and interesting portraits.</string>
+    <string name="dualcam_fusion_intro">Your foreground can be copied and pasted onto any photo in your Gallery.\n\nYou can try using different background photos to create new and interesting portraits.</string>
+    <string name="do_not_show_again">Do not show again</string>
+    <string name="trueportrait_touch_up">Touch up</string>
+    <string name="fusion_pick_background">Select background photo</string>
+
+    <string name="color">Color</string>
+    <string name="ok_continue">Continue</string>
+    <string name="frames">Frames</string>
+    <string name="beautify">Beautify</string>
+    <string name="dualcam">Dual camera</string>
+    <string name="trueportrait" translatable="false">TruePortrait</string>
+    <string name="foreground">Foreground</string>
+    <string name="background">Background</string>
+    <string name="brush_size">Brush Size</string>
+
+    <string name="pref_dualcam_intro_show_key" translatable="false">pref_dualcam_intro_show_key</string>
+    <string name="pref_trueportrait_intro_show_key" translatable="false">pref_trueportrait_intro_show_key</string>
+    <string name="pref_trueportrait_edit_intro_show_key" translatable="false">pref_trueportrait_edit_intro_show_key</string>
+    <string name="pref_trueportrait_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
+    <string name="pref_trueportrait_fusion_underlay_key" translatable="false">pref_trueportrait_fusion_underlay_key</string>
+    <string name="pref_dualcam_fusion_underlay_key" translatable="false">pref_dualcam_fusion_underlay_key</string>
+    <string name="pref_dualcam_fusion_intro_show_key" translatable="false">pref_trueportrait_fusion_intro_show_key</string>
+
+    <!--Filtershow dialog -->
+    <string name="filtershow_dialog_title">Custom filter</string>
+    <string name="filtershow_dialog_content">Allows you to create a photo filter.\n\nSelect a photo you like and use it as a filter for other photos</string>
+    <string name="filtershow_dialog_original_photo">Original photo</string>
+    <string name="filtershow_dialog_apply_photo">Colors to apply</string>
+    <string name="filtershow_dialog_checkbox">Do not show again</string>
+    <string name="pref_filtergenerator_intro_show_key" translatable="false">pref_filtergenerator_intro_show_key</string>
+    <string name="filtershow_preset_title">Custom</string>
+    <string name="filtershow_preset_rename">Rename</string>
+    <string name="delete_before_exit">Delete filter?</string>
+    <string name="rename_before_exit">Rename filter</string>
+    <string name="filter_name">Filter name</string>
+    <string name="filter_name_notification">Name cannot be empty.</string>
+    <string name="filter_name_duplicate">Name already exists, please enter a different one.</string>
+    <string name="watermark_location">Location</string>
+    <string name="watermark_time">Time</string>
+    <string name="watermark_weather">Weather</string>
+    <string name="watermark_emotions">Emotions</string>
+    <string name="watermark_food">Food</string>
+    <string name="location_pin" translatable="false">LOCATION_PIN</string>
+    <string name="location_city" translatable="false">LOCATION_CITY</string>
+    <string name="location_hello" translatable="false">LOCATION_HELLO</string>
+    <string name="location_stamp" translatable="false">LOCATION_STAMP</string>
+    <string name="time_hourglass" translatable="false">TIME_HOURGLASS</string>
+    <string name="time_timestamp" translatable="false">TIME_TIMESTAMP</string>
+    <string name="time_sunrise" translatable="false">TIME_SUNRISE</string>
+    <string name="time_calendar" translatable="false">TIME_CALENDAR</string>
+    <string name="weather_rain" translatable="false">WEATHER_RAIN</string>
+    <string name="weather_snow" translatable="false">WEATHER_SNOW</string>
+    <string name="weather_sun" translatable="false">WEATHER_SUN</string>
+    <string name="weather_artistic_sun" translatable="false">WEATHER_ARTISTIC_SUN</string>
+    <string name="emotion_party" translatable="false">EMOTION_PARTY</string>
+    <string name="emotion_peace" translatable="false">EMOTION_PEACE</string>
+    <string name="emotion_cry" translatable="false">EMOTION_CRY</string>
+    <string name="emotion_happy" translatable="false">EMOTION_HAPPY</string>
+    <string name="food_fork_knife" translatable="false">FOOD_FORK_KNIFE</string>
+    <string name="food_tea_time" translatable="false">FOOD_TEA_TIME</string>
+    <string name="food_cheers" translatable="false">FOOD_CHEERS</string>
+    <string name="food_yum" translatable="false">FOOD_YUM</string>
+
+    <!--Filtershow Toast -->
+    <string name="no_faces_found">No faces found</string>
+    <string name="image_size_too_small">Image size too small</string>
+    <string name="not_support_gif">Gif files are not supported, please choose another photo</string>
+</resources>
diff --git a/res/values/codeaurora_strings.xml b/res/values/codeaurora_strings.xml
new file mode 100644
index 0000000..b6f5a73
--- /dev/null
+++ b/res/values/codeaurora_strings.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+Copyright (C) 2014-2016 The CyanogenMod Project
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Strings for step option settins -->
+    <string name="setp_option_name">Step</string>
+    <string name="step_option_desc">Customize fast forward/rewind step</string>
+    <string name="setp_option_three_second">3 seconds</string>
+    <string name="setp_option_six_second">6 seconds</string>
+
+    <string name="loop">"Loop"</string>
+    <string name="single">"Single"</string>
+    <string name="stereo">"Stereo"</string>
+    <string name="speaker_on">Speaker ON</string>
+    <string name="speaker_off">Speaker OFF</string>
+    <string name="speaker_need_headset">Plug in headphones to use this feature.</string>
+    <string name="single_track">"Single track"</string>
+    <string name="input_url">"Enter URL"</string>
+    <string name="streaming_settings">"Streaming settings"</string>
+    <string name="next">"Next"</string>
+    <string name="previous">"Previous"</string>
+
+    <string name="rtp_rtcp" translatable="false">RTP/RTCP</string>
+    <string name="buffer_size">Buffer size</string>
+    <string name="apn">Preferred APN</string>
+    <string name="rtp_min_port">Min port</string>
+    <string name="rtp_max_port">Max port</string>
+    <string name="set_rtp_min_port">Set min port</string>
+    <string name="set_rtp_max_port">Set max port</string>
+    <string name="set_buffer_size">Set buffer size</string>
+    <string name="set_apn">Select preferred APN</string>
+    <string name="setting">Settings</string>
+
+    <string name="server_timeout_title">"Server timeout"</string>
+    <string name="server_timeout_message">"Reconnect to the server to play the video?"</string>
+    <string name="videoview_error_text_cannot_connect_retry">"Connection failed, trying to reconnect to %1$d\u2026"</string>
+    <string name="media_controller_live">Live</string>
+    <string name="media_controller_playing">Playing</string>
+    <string name="media_controller_connecting">Connecting\u2026</string>
+
+    <string name="bookmark_add">"Add bookmark"</string>
+    <string name="bookmark_display">"Show bookmarks"</string>
+    <string name="bookmark_empty">"No bookmarks"</string>
+    <string name="bookmark_exist">"Bookmark already exists"</string>
+    <string name="bookmark_add_success">"Bookmark added"</string>
+    <string name="bookmark_list">"Bookmarks"</string>
+    <string name="bookmark_title">"Title"</string>
+    <string name="bookmark_location">"Location"</string>
+    <string name="delete_all">"Delete all"</string>
+    <string name="default_title">"Default title"</string>
+
+    <!-- A label describing to link website [CHAR LIMIT=30] -->
+    <string name="more_image">More images</string>
+    <string name="website_for_more_image" translatable="false"></string>
+
+    <!-- Toast if the muted video is not supported. [CHAR LIMIT=80] -->
+    <string name="mute_nosupport">Can not mute : video not supported</string>
+
+    <!-- The message is shown in toast when click showOnMap Menu and there is no map app -->
+    <string name="map_activity_not_found_err">There is no maps app installed to show the location.</string>
+
+    <plurals name="number_of_videos">
+        <item quantity="one">%1$d video</item>
+        <item quantity="other">%1$d videos</item>
+    </plurals>
+
+
+
+
+
+    <!-- Toast message for share items -->
+    <string name="cannot_share_items">Max selected items for share is 300</string>
+
+    <string name="share_dialogue_title">Share via</string>
+
+    <!-- When grouping photos by peoples, the label used for photos that don't
+         have people information in them [CHAR LIMIT=20]-->
+    <string name="no_faces">No faces</string>
+
+    <!-- The tips of trimming video -->
+    <string name="fail_trim">Sorry, this video file can not be trimmed</string>
+    <string name="can_not_trim">Only mp4 and 3gp files can be trimmed</string>
+
+    <string name="drm_license_info">DRM license info</string>
+
+    <!-- Timeline screen title -->
+    <string name="timeline_title">Timeline</string>
+    <!-- Albums screen title -->
+    <string name="albums_title">Albums</string>
+    <!-- Videos screen title -->
+    <string name="videos_title">Videos</string>
+
+    <string name="action_viewtype_list">List view</string>
+    <string name="action_viewtype_grid" translatable="false">@string/switch_photo_grid</string>
+    <string name="tvEmptyAlbum">No photos found</string>
+    <string name="tvEmptyVideos">No videos found</string>
+
+    <string name="text_makeup_whiten">Whiten</string>
+    <string name="text_makeup_Soften">Soften</string>
+    <string name="text_makeup_trimface">Trimface</string>
+    <string name="text_makeup_bigeye">Bigeye</string>
+
+    <string name="truescanner_normal">Normal</string>
+    <string name="truescanner_white">Whiteboard</string>
+    <string name="truescanner">TrueScanner</string>
+    <string name="truescanner_remove_glare">Remove Glare</string>
+    <string name="hazebuster_acts">Haze Buster</string>
+    <string name="seestraight_acts">See Straight</string>
+    <string name="seestraight_input_image_is_small">Input image is too small to process.</string>
+    <string name="seestraight_process_fail">Couldn\'t process the image.</string>
+
+    <string name="trim_video_exit_title">Discard changes?</string>
+    <string name="trim_video_exit_msg">Discard the changes made to this video?</string>
+    <string name="trim_video_exit_discard">DISCARD</string>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
old mode 100644
new mode 100755
index f1fa300..9388e98
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -14,56 +14,61 @@
      limitations under the License.
 -->
 <resources>
-    <color name="default_background">#000</color>
-    <color name="ic_launcher_gallery_background">#4285f4</color>
+
+    <color name="default_background">@color/white</color>
 
     <!-- configuration for album set page -->
-    <color name="albumset_background">#1A1A1A</color>
-    <color name="albumset_placeholder">#333</color>
-    <color name="albumset_label_background">#EE414143</color>
-    <color name="albumset_label_title">#FBFBFB</color>
-    <color name="albumset_label_count">#A9ABAD</color>
+    <color name="albumset_background">@color/white</color>
+    <color name="albumset_placeholder">@color/black_transparent_3</color>
+    <color name="albumset_label_background">@color/black_transparent_4</color>
+    <color name="albumset_label_title">@color/white</color>
+    <color name="albumset_label_count">@color/white</color>
+    <color name="albumlist_label_title">@color/black_transparent_4</color>
+
+    <color name="darker_transparent">@color/black_transparent_5</color>
 
     <!-- configuration for album page -->
-    <color name="album_background">#1A1A1A</color>
-    <color name="album_placeholder">#333</color>
+    <color name="album_background">@color/white</color>
+    <color name="album_placeholder">@color/white</color>
 
     <!-- configuration for photo page -->
-    <color name="photo_background">#1A1A1A</color>
-    <color name="photo_placeholder">#333</color>
+    <color name="photo_background">@color/black</color>
+    <color name="photo_placeholder">@color/light_black</color>
+    <color name="photo_page_action_bar">#8A000000</color>
+    <color name="photo_page_bottom_panel">#8A000000</color>
 
     <!-- configuration for manage cache page -->
-    <color name="cache_background">#1A1A1A</color>
-    <color name="cache_placeholder">#333</color>
+    <color name="cache_background">@color/primary</color>
+    <color name="cache_placeholder">@color/light_black</color>
 
-    <color name="bitmap_screennail_placeholder">#333</color>
+    <color name="bitmap_screennail_placeholder">@color/light_black</color>
 
-    <color name="slideshow_background">#1A1A1A</color>
+    <color name="slideshow_background">@color/light_black</color>
 
     <color name="button_dark_transparent_background">#6000</color>
 
     <color name="ingest_highlight_semitransparent">#8833b5e5</color>
-    <color name="ingest_date_tile_text">#33b5e5</color>
+    <color name="ingest_date_tile_text">@color/accent</color>
 
     <!-- Camera resources below -->
 
-    <color name="recording_time_elapsed_text">#FFFFFFFF</color>
+    <color name="recording_time_elapsed_text">@color/white</color>
     <color name="recording_time_remaining_text">#FFFF0033</color>
     <color name="on_viewfinder_label_background_color">#77333333</color>
-    <color name="review_control_pressed_color">#FF33B5E5</color>
+    <color name="review_control_pressed_color">@color/accent</color>
     <color name="review_control_pressed_fan_color">#3F33B5E5</color>
-    <color name="review_background">#FF000000</color>
+    <color name="review_background">@color/black</color>
     <color name="icon_disabled_color">#DD777777</color>
     <color name="time_lapse_arc">#FFC5C5C5</color>
     <color name="indicator_background">#40000000</color>
-    <color name="popup_title_color">#ff33b5e5</color>
+    <color name="popup_title_color">@color/accent</color>
     <color name="popup_background">#ff282828</color>
     <color name="pano_progress_empty">#FF2E2E2E</color>
     <color name="pano_progress_done">#FF33525E</color>
     <color name="pano_progress_indication">#FF0099CC</color>
     <color name="pano_progress_indication_fast">#FFFF2222</color>
-    <color name="mode_selection_border">#33B5E5</color>
-    <color name="holo_blue_light">#ff33b5e5</color>
+    <color name="mode_selection_border">@color/accent</color>
+    <color name="holo_blue_light">@color/accent</color>
     <color name="bright_foreground_disabled_holo_dark">#ff4c4c4c</color>
     <color name="bright_foreground_holo_dark">#fff3f3f3</color>
     <color name="face_detect_start">#80ffffff</color>
@@ -71,4 +76,19 @@
     <color name="face_detect_fail">#80d05060</color>
     <color name="gray">#FFAAAAAA</color>
 
+    <color name="highlight">#f41e26</color>
+    <color name="lowlight">#650101</color>
+    <color name="grey">#e7e7e7</color>
+    <color name="disabled_knob">#575757</color>
+    <color name="toolbar_theme">@color/primary</color>
+    <color name="multiselect_background">@color/white</color>
+    <color name="edit_background">@color/black</color>
+    <color name="edit_actionbar_background">@color/black</color>
+    <color name="dialog_button_color">#009688</color>
+    <color name="timeline_title_text_color">@color/black_transparent_4</color>
+    <color name="timeline_title_number_text_color">@color/black_transparent_3</color>
+    <color name="timeline_title_background_color">@color/white</color>
+
+    <color name="navigation_accent_disabled">#747474</color>
+    <color name="navigation_accent_enabled">@color/white</color>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 33e1e14..5af45db 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -1,5 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- Copyright (c) 2014, The Linux Foundation. All rights reserved.
+     Not a Contribution.
+
+     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.
@@ -19,4 +22,5 @@
 <resources>
     <!-- Maximum recording length in milliseconds. 0 means unlimited. -->
     <integer name="max_video_recording_length">0</integer>
+    <bool name="config_show_more_images">false</bool>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
old mode 100644
new mode 100755
index ef742d2..49aa5d5
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -112,23 +112,52 @@
     <!-- configuration for legacy album set page -->
     <integer name="albumset_rows_land">2</integer>
     <integer name="albumset_rows_port">3</integer>
-    <dimen name="albumset_padding_top">7dp</dimen>
-    <dimen name="albumset_padding_bottom">7dp</dimen>
-    <dimen name="albumset_slot_gap">7dp</dimen>
+    <integer name="albumset_cols_land">3</integer>
+    <integer name="albumset_cols_port">2</integer>
 
-    <dimen name="albumset_label_background_height">30dp</dimen>
-    <dimen name="albumset_title_offset">10dp</dimen>
-    <dimen name="albumset_count_offset">10dp</dimen>
-    <dimen name="albumset_title_font_size">12sp</dimen>
-    <dimen name="albumset_count_font_size">9sp</dimen>
+    <dimen name="albumset_padding_top">4dp</dimen>
+    <dimen name="albumset_padding_bottom">4dp</dimen>
+    <dimen name="albumset_padding_left">4dp</dimen>
+    <dimen name="albumset_padding_right">4dp</dimen>
+    <dimen name="albumset_slot_gap">4dp</dimen>
+    <dimen name="albumset_label_background_height">48dp</dimen>
+    <dimen name="albumset_title_offset">12dp</dimen>
+    <dimen name="albumset_count_offset">18dp</dimen>
+    <dimen name="albumset_title_font_size">16sp</dimen>
+    <dimen name="albumset_count_font_size">16sp</dimen>
     <dimen name="albumset_left_margin">2dp</dimen>
     <dimen name="albumset_title_right_margin">20dp</dimen>
+    <dimen name="albumset_title_left_margin">12dp</dimen>
+    <dimen name="albumset_count_right_margin">18dp</dimen>
     <dimen name="albumset_icon_size">25dp</dimen>
 
+      <!-- configuration for albumset page in Landscape-->
+    <dimen name="albumset_slot_gap_land">4dp</dimen>
+    <dimen name="albumset_padding_top_land">4dp</dimen>
+    <dimen name="albumset_padding_bottom_land">4dp</dimen>
+    <dimen name="albumset_padding_left_land">4dp</dimen>
+    <dimen name="albumset_padding_right_land">4dp</dimen>
+
     <!-- configuration for album page -->
     <integer name="album_rows_land">2</integer>
     <integer name="album_rows_port">4</integer>
-    <dimen name="album_slot_gap">5dp</dimen>
+    <integer name="album_cols_land">5</integer>
+    <integer name="album_cols_port">3</integer>
+
+    <dimen name="album_slot_gap">3dp</dimen>
+    <dimen name="album_padding_top">3dp</dimen>
+    <dimen name="album_padding_bottom">3dp</dimen>
+    <dimen name="album_padding_left">3dp</dimen>
+    <dimen name="album_padding_right">3dp</dimen>
+
+      <!-- configuration for album page in Landscape-->
+    <dimen name="album_slot_gap_land">3dp</dimen>
+    <dimen name="album_padding_top_land">3dp</dimen>
+    <dimen name="album_padding_bottom_land">3dp</dimen>
+    <dimen name="album_padding_left_land">3dp</dimen>
+    <dimen name="album_padding_right_land">3dp</dimen>
+
+    <dimen name="photo_view_video_icon_size">48dp</dimen>
 
     <!-- configuration for manage page -->
     <dimen name="cache_pin_size">24dp</dimen>
@@ -139,9 +168,10 @@
 
     <!--  configuration for filtershow UI -->
     <dimen name="thumbnail_size">96dip</dimen>
-    <dimen name="thumbnail_margin">3dip</dimen>
+    <dimen name="thumbnail_margin">2dip</dimen>
     <dimen name="action_item_height">175dip</dimen>
     <dimen name="touch_circle_size">8dp</dimen>
+    <dimen name="crop_indicator_size">40dp</dimen>
 
     <!-- configuration for album set page -->
     <dimen name="album_set_item_image_height">120dp</dimen>
@@ -152,4 +182,59 @@
     <dimen name="photoeditor_text_padding">10dp</dimen>
     <dimen name="photoeditor_original_text_size">18dp</dimen>
     <dimen name="photoeditor_original_text_margin">4dp</dimen>
+    <dimen name="timeline_grid_vertical_space">3dp</dimen>
+    <dimen name="slot_width">174dp</dimen>
+    <dimen name="slot_height">174dp</dimen>
+    <dimen name="toolbar_height">80dp</dimen>
+    <dimen name="slot_width_album">116dp</dimen>
+    <dimen name="slot_height_album">116dp</dimen>
+    <dimen name="crop_icon_size">30dp</dimen>
+    <dimen name="crop_icon_size_landscape">24dp</dimen>
+    <dimen name="crop_panel_height_lanscape">60dp</dimen>
+    <dimen name="crop_icon_margin_padding">20dp</dimen>
+    <dimen name="crop_text_margin_padding">6dp</dimen>
+    <dimen name="crop_rect_stroke">2dp</dimen>
+    <dimen name="crop_line_stroke">1dp</dimen>
+    <dimen name="crop_corner_length">14dp</dimen>
+
+    <!-- configuration for album page in listview -->
+    <integer name="albumlist_cols_land">1</integer>
+    <integer name="albumlist_cols_port">1</integer>
+
+    <dimen name="albumlist_padding_top">18dp</dimen>
+    <dimen name="slot_height_albumlist">40dp</dimen>
+    <dimen name="albumlist_slot_gap">18dp</dimen>
+    <dimen name="albumlist_thumb_size">40dp</dimen>
+    <dimen name="albumlist_left_margin">16dp</dimen>
+    <dimen name="albumlist_title_margin">16dp</dimen>
+    <dimen name="albumlist_title_font_size">16sp</dimen>
+    <dimen name="albumlist_label_background_height">40dp</dimen>
+    <dimen name= "edit_main_font">13sp</dimen>
+    <dimen name="dialog_text_size">14sp</dimen>
+
+    <dimen name="timeline_port_slot_gap">3dp</dimen>
+    <dimen name="timeline_land_slot_gap">3dp</dimen>
+    <dimen name="timeline_land_margin">3dp</dimen>
+    <dimen name="timeline_port_margin">3dp</dimen>
+    <dimen name="timeline_title_height">48dp</dimen>
+    <dimen name="timeline_title_font_size">14sp</dimen>
+    <dimen name="timeline_title_margin">16dp</dimen>
+
+    <dimen name="timebar_height">60dp</dimen>
+    <dimen name="timebar_margin">30dp</dimen>
+    <dimen name="timebar_time_margin">45dp</dimen>
+    <dimen name="livestream_icon_padding">12dp</dimen>
+
+    <!-- configuration for gesture controller indicator. -->
+    <dimen name="controller_indicator_width">80dp</dimen>
+    <dimen name="controller_indicator_height">90dp</dimen>
+    <dimen name="controller_indicator_padding_v">15dp</dimen>
+    <dimen name="controller_indicator_padding_h">10dp</dimen>
+    <dimen name="controller_indicator_icon_size">36dp</dimen>
+    <dimen name="controller_indicator_text_size">16sp</dimen>
+
+    <dimen name="toolbar_title_text_size">20dp</dimen>
+    <dimen name="toolbar_exit_padding_left">16dp</dimen>
+
+    <dimen name="watermark_default_size">75dp</dimen>
 </resources>
diff --git a/res/values/filtershow_color.xml b/res/values/filtershow_color.xml
index 4fb4495..f9b05d9 100644
--- a/res/values/filtershow_color.xml
+++ b/res/values/filtershow_color.xml
@@ -19,8 +19,8 @@
     <color name="green">#00FF00</color>
     <color name="red">#FF0000</color>
     <color name="blue">#0000FF</color>
-    <color name="text_toolbar">#FFFFFF</color>
-    <color name="background_screen">#101010</color>
+    <color name="text_toolbar">@color/white</color>
+    <color name="background_screen">#212121</color>
     <color name="background_toolbar">#363949</color>
     <color name="background_main_toolbar">#232323</color>
     <color name="toolbar_separation_line">#333333</color>
@@ -32,22 +32,42 @@
     <color name="filtershow_stateview_end_background">#232323</color>
     <color name="filtershow_stateview_end_text">#a7a7a7</color>
     <color name="filtershow_stateview_background">#464646</color>
-    <color name="filtershow_stateview_text">#FFFFFF</color>
+    <color name="filtershow_stateview_text">@color/white</color>
     <color name="filtershow_stateview_selected_background">#c8c8c8</color>
-    <color name="filtershow_stateview_selected_text">#000000</color>
+    <color name="filtershow_stateview_selected_text">@color/black</color>
     <color name="filtershow_categoryview_background">#1a1a1a</color>
-    <color name="filtershow_categoryview_text">#a7a7a7</color>
-    <color name="filtershow_category_selection">#ffffffff</color>
-    <color name="gradcontrol_point_center">#ffffffff</color>
-    <color name="gradcontrol_point_edge">#ffffffff</color>
+    <color name="filtershow_categoryview_text">@color/white</color>
+    <color name="filtershow_category_selection">#4592F9</color>
+    <color name="gradcontrol_point_center">@color/white</color>
+    <color name="gradcontrol_point_edge">@color/white</color>
     <color name="gradcontrol_graypoint_center">#888888</color>
     <color name="gradcontrol_graypoint_edge">#BBBBBB</color>
     <color name="gradcontrol_point_shadow_start">#66000000</color>
-    <color name="gradcontrol_point_shadow_end">#00000000</color>
-    <color name="gradcontrol_line_color">#FFFFFF</color>
-    <color name="gradcontrol_line_shadow">#000000</color>
+    <color name="gradcontrol_point_shadow_end">@android:color/transparent</color>
+    <color name="gradcontrol_line_color">@color/white</color>
+    <color name="gradcontrol_line_shadow">@color/black</color>
     <color name="draw_rect_border">#888888</color>
-    <color name="color_chooser_unslected_border">#00000000</color>
+    <color name="color_chooser_unslected_border">#3d4040</color>
     <color name="color_chooser_slected_border">#a7a7a7</color>
+    <color name="filtershow_image_mask">#4d000000</color>
+    <color name="filtershow_info_text">#DE000000</color>
+    <color name="filtershow_info_test">#00FF0000</color>
 
-</resources>
\ No newline at end of file
+    <color name="filtershow_color_none">#80000000</color>
+    <color name="filtershow_color_punch">#80000000</color>
+    <color name="filtershow_color_vintage">#80000000</color>
+    <color name="filtershow_color_bw">#80000000</color>
+    <color name="filtershow_color_bleach">#80000000</color>
+    <color name="filtershow_color_instant">#80000000</color>
+    <color name="filtershow_color_latte">#80000000</color>
+    <color name="filtershow_color_blue">#80000000</color>
+    <color name="filtershow_color_litho">#80000000</color>
+    <color name="filtershow_color_xprocess">#80000000</color>
+
+    <color name="iconview_bottom_color">#80000000</color>
+    <color name="bottom_panel_background_color">#A5000000</color>
+    <color name="crop_panel_background_color">#A5000000</color>
+    <color name="crop_text_color">#4f92e9</color>
+    <color name="watermark_text_color">#80ffffff</color>
+    <color name="watermark_highlight_color">#4592F9</color>
+</resources>
diff --git a/res/values/filtershow_ids.xml b/res/values/filtershow_ids.xml
index 460da61..8cfb250 100644
--- a/res/values/filtershow_ids.xml
+++ b/res/values/filtershow_ids.xml
@@ -50,4 +50,15 @@
     <item type="id" name="editorParametric" />
     <item type="id" name="editorGrad" />
     <item type="id" name="editorChanSat" />
+    <item type="id" name="editorMakeup" />
+    <item type="id" name="editorDualCam" />
+    <item type="id" name="editorDualCamSketch" />
+    <item type="id" name="editorDualCamFusion" />
+    <item type="id" name="trueScannerEditor" />
+    <item type="id" name="hazeBusterEditor" />
+    <item type="id" name="seeStraightEditor" />
+    <item type="id" name="editorTruePortraitBasic" />
+    <item type="id" name="editorTruePortraitImageOnly" />
+    <item type="id" name="editorTruePortraitMask" />
+    <item type="id" name="editorTruePortraitFusion" />
 </resources>
diff --git a/res/values/filtershow_styles.xml b/res/values/filtershow_styles.xml
index 4162ccd..6fa76a2 100644
--- a/res/values/filtershow_styles.xml
+++ b/res/values/filtershow_styles.xml
@@ -56,13 +56,20 @@
         <item name="android:indeterminateOnly">false</item>
         <item name="android:progressDrawable">@drawable/filtershow_slider</item>
         <item name="android:indeterminateDrawable">@drawable/filtershow_slider</item>
-        <item name="android:minHeight">13dip</item>
-        <item name="android:maxHeight">13dip</item>
-        <item name="android:thumb">@drawable/filtershow_scrubber</item>
-        <item name="android:thumbOffset">16dip</item>
+        <item name="android:minHeight">4dip</item>
+        <item name="android:maxHeight">4dip</item>
+        <item name="android:thumb">@drawable/adjust</item>
+        <item name="android:thumbOffset">0dip</item>
         <item name="android:focusable">true</item>
-        <item name="android:paddingStart">16dip</item>
-        <item name="android:paddingEnd">16dip</item>
+        <item name="android:background">@null</item>
+    </style>
+
+    <style name="DefaultFillColor">
+        <item name="fillColorSelector">#FFFFFF</item>
+    </style>
+
+    <style name="SelectedFillColor">
+        <item name="fillColorSelector">#4592F9</item>
     </style>
 
 </resources>
\ No newline at end of file
diff --git a/res/values/filtershow_values.xml b/res/values/filtershow_values.xml
index a788afe..a7f43f8 100644
--- a/res/values/filtershow_values.xml
+++ b/res/values/filtershow_values.xml
@@ -16,22 +16,30 @@
 
 <resources>
     <!-- Specify the screen orientation -->
-    <bool name="only_use_portrait">true</bool>
+    <bool name="only_use_portrait">false</bool>
 
     <!-- Text size for the state panel -->
     <dimen name="state_panel_text_size">16dip</dimen>
 
+    <!-- Bottom Panel Height -->
+    <dimen name="bottom_panel_height">50dip</dimen>
+
     <!-- Category Panel Height -->
-    <dimen name="category_panel_height">86dip</dimen>
+    <dimen name="category_panel_height">90dip</dimen>
 
     <!-- Category Panel Icon Size -->
-    <dimen name="category_panel_icon_size">64dip</dimen>
+    <dimen name="category_panel_icon_size">80dip</dimen>
+
+    <dimen name="category_actionbar_panel_height">50dip</dimen>
 
     <!-- Category Panel Text Size -->
-    <dimen name="category_panel_text_size">13dip</dimen>
+    <dimen name="category_panel_text_size">11dip</dimen>
 
     <!-- Category Panel Text Size -->
-    <dimen name="category_panel_margin">4dip</dimen>
+    <dimen name="category_panel_margin">10dip</dimen>
+
+    <!-- Category Panel height of bottom rect -->
+    <dimen name="category_panel_bottom_rect_height">20dip</dimen>
 
     <!-- Grad filter dot size -->
     <dimen name="gradcontrol_dot_size">20dip</dimen>
@@ -65,4 +73,16 @@
 
     <!-- Glow effect size -->
     <dimen name="edge_glow_size">50dip</dimen>
+    <dimen name="swap_button_width">168dp</dimen>
+    <dimen name="swap_button_height">32dp</dimen>
+    <dimen name="compare_margin_top">74dp</dimen>
+    <dimen name="compare_margin_right">10dp</dimen>
+    <dimen name="compare_margin_top_scaled">96dp</dimen>
+    <dimen name="compare_margin_right_scaled">60dp</dimen>
+    <dimen name="color_button_width">36dp</dimen>
+    <dimen name="color_button_height">36dp</dimen>
+    <dimen name="seekbar_width_filter">216dp</dimen>
+    <dimen name="scaled_image_height">454dp</dimen>
+    <dimen name="scaled_image_width">330dp</dimen>
+
 </resources>
\ No newline at end of file
diff --git a/res/values/iconbutton_styles.xml b/res/values/iconbutton_styles.xml
index e33460a..5e34063 100644
--- a/res/values/iconbutton_styles.xml
+++ b/res/values/iconbutton_styles.xml
@@ -38,8 +38,8 @@
         <item name="android:textSize">13dp</item>
         <item name="android:scaleType">centerInside</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">3dp</item>
-        <item name="android:paddingRight">3dp</item>
+        <item name="android:paddingStart">3dp</item>
+        <item name="android:paddingEnd">3dp</item>
         <item name="android:paddingTop">6dp</item>
         <item name="android:paddingBottom">6dp</item>
         <item name="android:ellipsize">marquee</item>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index f5b4a48..93ea5c0 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -23,4 +23,6 @@
 
     <item type="id" name="ingest_notification_scanning" />
     <item type="id" name="ingest_notification_importing" />
+
+    <item type="id" name="empty_album" />
 </resources>
diff --git a/res/values/mediapicker_colors.xml b/res/values/mediapicker_colors.xml
new file mode 100644
index 0000000..765e8b1
--- /dev/null
+++ b/res/values/mediapicker_colors.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<resources>
+
+    <color name="picker_imageloading">#252528</color>
+    <color name="picker_grid_state_pressed">#DC007aff</color>
+    <color name="picker_grid_state_focused">#DC007aff</color>
+    <color name="picker_color">#007aff</color>
+
+</resources>
diff --git a/res/values/mediapicker_dimens.xml b/res/values/mediapicker_dimens.xml
new file mode 100644
index 0000000..ef432b5
--- /dev/null
+++ b/res/values/mediapicker_dimens.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+  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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+  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.
+-->
+
+<resources>
+
+    <dimen name="picker_photo_size">75dp</dimen>
+    <dimen name="picker_photo_spacing">4dp</dimen>
+    <dimen name="picker_border_size">3dp</dimen>
+    <dimen name="mediapicker_default_height">215dp</dimen>
+    <dimen name="mediapicker_land_height">90dp</dimen>
+</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
old mode 100644
new mode 100755
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 33dcbec..788339c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -15,31 +15,49 @@
 -->
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <style name="Theme.GalleryBase" parent="android:Theme.Holo">
+    <style name="Theme.GalleryBase" parent="android:Theme.Material">
+        <item name="android:colorPrimary">@color/primary</item>
+        <item name="android:colorPrimaryDark">@color/primaryDark</item>
+        <item name="android:colorAccent">@color/accent</item>
         <item name="listPreferredItemHeightSmall">48dp</item>
         <item name="switchStyle">@android:style/Widget.CompoundButton</item>
     </style>
-    <style name="Theme.Gallery.Dialog" parent="android:Theme.Holo.Dialog"/>
-    <style name="Theme.Gallery" parent="Theme.GalleryBase">
-        <item name="android:displayOptions"></item>
+
+    <style name="Theme.Gallery.Dialog" parent="android:Theme.Material.Dialog" />
+
+    <style name="Theme.Gallery" parent="android:Theme.Material.Light">
+        <item name="android:colorPrimary">@color/primary</item>
+        <item name="android:colorPrimaryDark">@color/primaryDark</item>
+        <item name="android:colorAccent">@color/accent</item>
         <item name="android:windowContentOverlay">@null</item>
-        <item name="android:actionBarStyle">@style/Holo.ActionBar</item>
-        <item name="android:windowBackground">@android:color/black</item>
-        <item name="android:colorBackground">@null</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:windowTranslucentStatus">true</item>
+        <item name="android:windowTranslucentNavigation">false</item>
+        <item name="android:windowActionModeOverlay">true</item>
+        <item name="android:actionOverflowButtonStyle">@style/WhiteOverflow</item>
+        <item name="android:logo">@android:color/transparent</item>
     </style>
     <style name="Theme.FilterShow" parent="Theme.Gallery">
         <item name="android:windowBackground">@null</item>
+        <item name="android:actionBarStyle">@style/FilterShowActionBar</item>
+        <item name="android:toolbarStyle">@style/FilterShowToolbar</item>
+    </style>
+    <style name="FilterShowToolbar" parent="@android:style/Widget.Toolbar">
+        <item name="android:contentInsetStart">0dp</item>
+    </style>
+    <style name="Theme.MovieActivity" parent="android:Theme.DeviceDefault.Light.DarkActionBar">
     </style>
     <style name="Theme.Crop" parent="Theme.GalleryBase">
         <item name="android:displayOptions"></item>
         <item name="android:windowContentOverlay">@null</item>
-        <item name="android:actionBarStyle">@style/Holo.ActionBar</item>
+        <item name="android:actionBarStyle">@style/Material.ActionBar</item>
         <item name="android:colorBackground">@null</item>
         <item name="android:colorBackgroundCacheHint">@null</item>
         <item name="android:windowBackground">@drawable/filtershow_tiled_background</item>
     </style>
-    <style name="Holo.ActionBar" parent="android:Widget.Holo.ActionBar">
+    <style name="Material.ActionBar" parent="android:Widget.Material.ActionBar">
         <item name="android:displayOptions">useLogo|showHome</item>
         <item name="android:background">@drawable/actionbar_translucent</item>
         <item name="android:backgroundStacked">@null</item>
@@ -48,14 +66,15 @@
         <item name="android:background">@null</item>
         <item name="android:src">@drawable/icn_media_play</item>
     </style>
-    <style name="DialogPickerTheme" parent="Theme.Gallery">
+    <style name="DialogPickerTheme" parent="android:Theme.Material">
+        <item name="android:colorPrimary">@color/primary</item>
+        <item name="android:colorPrimaryDark">@color/primaryDark</item>
     </style>
     <style name="Theme.ProxyLauncher" parent="@android:Theme.Translucent.NoTitleBar">
     </style>
-    <bool name="picker_is_dialog">false</bool>
-    <color name="darker_transparent">#C1000000</color>
-    <style name="ActionBarTwoLinePrimary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title"></style>
-    <style name="ActionBarTwoLineSecondary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle"></style>
+
+    <style name="ActionBarTwoLinePrimary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title"/>
+    <style name="ActionBarTwoLineSecondary" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle"/>
     <style name="ActionBarTwoLineItem">
         <item name="android:background">@drawable/action_bar_two_line_background</item>
     </style>
@@ -128,8 +147,8 @@
         <item name="android:orientation">horizontal</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">@dimen/setting_row_height</item>
-        <item name="android:paddingLeft">@dimen/setting_item_list_margin</item>
-        <item name="android:paddingRight">@dimen/setting_item_list_margin</item>
+        <item name="android:paddingStart">@dimen/setting_item_list_margin</item>
+        <item name="android:paddingEnd">@dimen/setting_item_list_margin</item>
         <item name="android:background">@drawable/setting_picker</item>
     </style>
     <style name="OnViewfinderLabel">
@@ -138,8 +157,8 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:singleLine">true</item>
         <item name="android:layout_margin">10dp</item>
-        <item name="android:paddingLeft">15dp</item>
-        <item name="android:paddingRight">15dp</item>
+        <item name="android:paddingStart">15dp</item>
+        <item name="android:paddingEnd">15dp</item>
         <item name="android:paddingTop">3dp</item>
         <item name="android:paddingBottom">3dp</item>
         <item name="android:textColor">@android:color/white</item>
@@ -150,8 +169,8 @@
         <item name="android:textAppearance">@android:style/TextAppearance.Medium</item>
     </style>
     <style name="EffectSettingGrid">
-        <item name="android:layout_marginLeft">@dimen/setting_item_list_margin</item>
-        <item name="android:layout_marginRight">@dimen/setting_item_list_margin</item>
+        <item name="android:layout_marginStart">@dimen/setting_item_list_margin</item>
+        <item name="android:layout_marginEnd">@dimen/setting_item_list_margin</item>
         <item name="android:paddingBottom">3dp</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
@@ -166,8 +185,8 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:paddingTop">9dp</item>
         <item name="android:paddingBottom">9dp</item>
-        <item name="android:paddingLeft">2dp</item>
-        <item name="android:paddingRight">2dp</item>
+        <item name="android:paddingStart">2dp</item>
+        <item name="android:paddingEnd">2dp</item>
         <item name="android:background">@drawable/setting_picker</item>
     </style>
     <style name="EffectSettingItemTitle">
@@ -188,12 +207,12 @@
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
         <item name="android:minHeight">@dimen/effect_setting_type_text_min_height</item>
-        <item name="android:paddingLeft">@dimen/effect_setting_type_text_left_padding</item>
+        <item name="android:paddingStart">@dimen/effect_setting_type_text_left_padding</item>
     </style>
     <style name="EffectTypeSeparator">
         <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_marginLeft">8dp</item>
-        <item name="android:layout_marginRight">8dp</item>
+        <item name="android:layout_marginStart">8dp</item>
+        <item name="android:layout_marginEnd">8dp</item>
         <item name="android:layout_marginBottom">14dp</item>
         <item name="android:layout_height">2dp</item>
         <item name="android:background">#2c2c2c</item>
@@ -215,8 +234,8 @@
         <item name="android:textColor">@color/primary_text</item>
         <item name="android:minHeight">48dip</item>
         <item name="android:minWidth">64dip</item>
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingStart">4dip</item>
+        <item name="android:paddingEnd">4dip</item>
     </style>
 
     <style name="ReviewControlText_xlarge">
@@ -224,8 +243,8 @@
         <item name="android:layout_width">wrap_content</item>
         <item name="android:background">@drawable/bg_pressed_exit_fading</item>
         <item name="android:gravity">center</item>
-        <item name="android:paddingLeft">2dp</item>
-        <item name="android:paddingRight">10dp</item>
+        <item name="android:paddingStart">2dp</item>
+        <item name="android:paddingEnd">10dp</item>
         <item name="android:paddingTop">10dp</item>
         <item name="android:paddingBottom">10dp</item>
         <item name="android:textSize">18sp</item>
@@ -240,7 +259,7 @@
         <item name="android:layout_height">wrap_content</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">@color/popup_title_color</item>
-        <item name="android:layout_marginLeft">10dp</item>
+        <item name="android:layout_marginStart">10dp</item>
     </style>
     <style name="PanoCustomDialogText_xlarge">
         <item name="android:textAppearance">@android:style/TextAppearance.Large</item>
@@ -266,9 +285,9 @@
         <item name="android:layout_height">match_parent</item>
     </style>
     <style name="UndoBar">
-        <item name="android:layout_marginLeft">4dp</item>
-        <item name="android:layout_marginRight">4dp</item>
-        <item name="android:paddingLeft">16dp</item>
+        <item name="android:layout_marginStart">4dp</item>
+        <item name="android:layout_marginEnd">4dp</item>
+        <item name="android:paddingStart">16dp</item>
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">48dp</item>
         <item name="android:layout_gravity">bottom</item>
@@ -284,12 +303,12 @@
         <item name="android:layout_height">match_parent</item>
         <item name="android:layout_marginTop">10dp</item>
         <item name="android:layout_marginBottom">10dp</item>
-        <item name="android:paddingRight">12dp</item>
+        <item name="android:paddingEnd">12dp</item>
     </style>
     <style name="UndoButton">
         <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">match_parent</item>
-        <item name="android:paddingRight">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
         <item name="android:textSize">12sp</item>
         <item name="android:gravity">center_vertical</item>
         <item name="android:textStyle">bold</item>
@@ -297,4 +316,48 @@
         <item name="android:drawablePadding">8dp</item>
         <item name="android:background">@drawable/bg_pressed</item>
     </style>
+
+    <style name="AppTheme" parent="Theme.AppCompat.Light">
+        <item name="android:windowDisablePreview">true</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:windowBackground">@android:color/black</item>
+        <item name="android:statusBarColor">#212121</item>
+        <item name="android:windowTranslucentNavigation">false</item>
+        <item name="android:windowActionBar">false</item>
+        <item name="android:windowActionModeOverlay">true</item>
+        <item name="android:actionModeBackground">@color/multiselect_background</item>
+        <item name="android:actionModeShareDrawable">@drawable/multiselect_share</item>
+        <item name="android:actionOverflowButtonStyle">@style/MyOverFlow</item>
+        <item name="android:homeAsUpIndicator">@drawable/back</item>
+        <item name="android:actionModeCloseDrawable">@drawable/multiselected_back</item>
+        <item name="android:windowNoTitle">true</item>
+    </style>
+
+    <style name="QueryTheme" parent="android:Theme.Material">
+        <item name="android:statusBarColor">#ab5810</item>
+    </style>
+
+    <style name="ToolbarTheme" parent="android:Theme.Material" >
+        <item name="android:actionOverflowButtonStyle">@style/WhiteOverflow</item>
+        <item name="colorPrimary">@color/primary</item>
+        <item name="colorPrimaryDark">@color/primaryDark</item>
+    </style>
+
+    <style name="ToolbarTitleStyle" parent="android:TextAppearance.Material.Widget.Toolbar.Title">
+        <item name="android:textSize">@dimen/toolbar_title_text_size</item>
+    </style>
+
+    <style name="ToolbarPopUpTheme" parent="android:Theme.Material.Light" />
+
+    <!-- Styles -->
+    <style name="MyOverFlow" parent="@android:style/Widget.Material.ActionButton.Overflow">
+        <item name="android:src">@drawable/multiselect_more</item>
+    </style>
+    <style name="WhiteOverflow" parent="@android:style/Widget.Material.ActionButton.Overflow">
+        <item name="android:src">@drawable/more</item>
+    </style>
+    <style name="FilterShowActionBar" parent="@android:style/Widget.Material.Light.ActionBar">
+        <item name="android:background">@color/edit_actionbar_background</item>
+        <item name="android:contentInsetStart">0dp</item>
+    </style>
 </resources>
diff --git a/res/xml/camera_preferences.xml b/res/xml/camera_preferences.xml
index 8c13a34..d17f472 100644
--- a/res/xml/camera_preferences.xml
+++ b/res/xml/camera_preferences.xml
@@ -15,7 +15,7 @@
 -->
 
 <PreferenceGroup
-        xmlns:camera="http://schemas.android.com/apk/res/com.android.gallery3d"
+        xmlns:camera="http://schemas.android.com/apk/res/org.codeaurora.gallery"
         camera:title="@string/pref_camera_settings_category">
     <IconListPreference
             camera:key="pref_camera_flashmode_key"
diff --git a/res/xml/provider_paths.xml b/res/xml/provider_paths.xml
new file mode 100755
index 0000000..9031aef
--- /dev/null
+++ b/res/xml/provider_paths.xml
@@ -0,0 +1,31 @@
+<!--
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ -->
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+    <external-path name="external_files" path="."/>
+</paths>
\ No newline at end of file
diff --git a/res/xml/rtsp_settings_preferences.xml b/res/xml/rtsp_settings_preferences.xml
new file mode 100755
index 0000000..895fb7d
--- /dev/null
+++ b/res/xml/rtsp_settings_preferences.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <PreferenceCategory android:title="@string/rtp_rtcp" >
+        <EditTextPreference
+            android:dialogTitle="@string/set_rtp_min_port"
+            android:inputType="number"
+            android:key="rtp_min_port"
+            android:maxLength="5"
+            android:order="1"
+            android:summary=""
+            android:title="@string/rtp_min_port" />
+        <EditTextPreference
+            android:dialogTitle="@string/set_rtp_max_port"
+            android:inputType="number"
+            android:key="rtp_max_port"
+            android:maxLength="5"
+            android:order="2"
+            android:summary=""
+            android:title="@string/rtp_max_port" />
+    </PreferenceCategory>
+    <PreferenceCategory android:title="@string/buffer_size" >
+        <EditTextPreference
+            android:dialogTitle="@string/set_buffer_size"
+            android:inputType="number"
+            android:key="buffer_size"
+            android:maxLength="10"
+            android:order="5"
+            android:summary=""
+            android:title="@string/buffer_size" />
+    </PreferenceCategory>
+    <PreferenceCategory android:title="@string/apn"
+        android:key="apn_category">
+        <PreferenceScreen
+            android:key="apn"
+            android:title="@string/set_apn" >
+        </PreferenceScreen>
+    </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/video_preferences.xml b/res/xml/video_preferences.xml
index 79154e6..de9dfcc 100644
--- a/res/xml/video_preferences.xml
+++ b/res/xml/video_preferences.xml
@@ -15,7 +15,7 @@
 -->
 
 <PreferenceGroup
-        xmlns:camera="http://schemas.android.com/apk/res/com.android.gallery3d"
+        xmlns:camera="http://schemas.android.com/apk/res/org.codeaurora.gallery"
         camera:title="@string/pref_camcorder_settings_category">
     <ListPreference
             camera:key="pref_video_quality_key"
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index b74af47..9462aed 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -15,6 +15,7 @@
  */
 package com.android.camera;
 
+import com.android.gallery3d.util.GalleryUtils;
 import com.android.gallery3d.util.IntentHelper;
 
 import android.app.Activity;
@@ -26,13 +27,16 @@
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
-        Intent intent = IntentHelper.getCameraIntent(CameraActivity.this);
-        // Since this is being launched from a homescreen shorcut,
-        // it's already in a new task. Start Camera activity and
-        // reset the task to its initial state if needed.
-        intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        startActivity(intent);
+
+        if (GalleryUtils.isCameraAvailable(CameraActivity.this)) {
+            Intent intent = IntentHelper.getCameraIntent();
+            // Since this is being launched from a homescreen shorcut,
+            // it's already in a new task. Start Camera activity and
+            // reset the task to its initial state if needed.
+            intent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            startActivity(intent);
+        }
         finish();
     }
 }
diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
old mode 100644
new mode 100755
index 9291556..a48371f
--- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java
+++ b/src/com/android/gallery3d/app/AbstractGalleryActivity.java
@@ -35,10 +35,10 @@
 import androidx.print.PrintHelper;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.Window;
 import android.view.WindowManager;
+import android.widget.Toolbar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
@@ -51,15 +51,17 @@
 
 import java.io.FileNotFoundException;
 
-public class AbstractGalleryActivity extends Activity implements GalleryContext {
+public abstract class AbstractGalleryActivity extends AbstractPermissionActivity
+        implements GalleryContext {
     private static final String TAG = "AbstractGalleryActivity";
     private GLRootView mGLRootView;
     private StateManager mStateManager;
     private GalleryActionBar mActionBar;
     private OrientationManager mOrientationManager;
     private TransitionStore mTransitionStore = new TransitionStore();
-    private boolean mDisableToggleStatusBar;
     private PanoramaViewHelper mPanoramaViewHelper;
+    private Toolbar mToolbar;
+    public boolean isTopMenuShow = false;
 
     private AlertDialog mAlertDialog = null;
     private BroadcastReceiver mMountReceiver = new BroadcastReceiver() {
@@ -70,11 +72,12 @@
     };
     private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED);
 
+    private static final String DEFAULT_PRINT_JOB_NAME = "print job";
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         mOrientationManager = new OrientationManager(this);
-        toggleStatusBarByOrientation();
         getWindow().setBackgroundDrawable(null);
         mPanoramaViewHelper = new PanoramaViewHelper(this);
         mPanoramaViewHelper.onCreate();
@@ -98,7 +101,6 @@
         mStateManager.onConfigurationChange(config);
         getGalleryActionBar().onConfigurationChanged();
         invalidateOptionsMenu();
-        toggleStatusBarByOrientation();
     }
 
     @Override
@@ -203,6 +205,12 @@
     @Override
     protected void onResume() {
         super.onResume();
+        // If top menu shows, GLView is active,
+        // so don't need to resume it.
+        if (isTopMenuShow) {
+            isTopMenuShow = false;
+            return;
+        }
         mGLRootView.lockRenderThread();
         try {
             getStateManager().resume();
@@ -217,6 +225,10 @@
     @Override
     protected void onPause() {
         super.onPause();
+        // If top menu shows, don't pause GLView,
+        // so it can redraw when rotating.
+        if (isTopMenuShow)
+            return;
         mOrientationManager.pause();
         mGLRootView.onPause();
         mGLRootView.lockRenderThread();
@@ -283,30 +295,10 @@
         }
     }
 
-    protected void disableToggleStatusBar() {
-        mDisableToggleStatusBar = true;
-    }
-
-    // Shows status bar in portrait view, hide in landscape view
-    private void toggleStatusBarByOrientation() {
-        if (mDisableToggleStatusBar) return;
-
-        Window win = getWindow();
-        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
-            win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        } else {
-            win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
-        }
-    }
-
     public TransitionStore getTransitionStore() {
         return mTransitionStore;
     }
 
-    public PanoramaViewHelper getPanoramaViewHelper() {
-        return mPanoramaViewHelper;
-    }
-
     protected boolean isFullscreen() {
         return (getWindow().getAttributes().flags
                 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
@@ -351,18 +343,54 @@
         if (uri == null) {
             return;
         }
-        String path = ImageLoader.getLocalPathFromUri(this, uri);
-        if (path != null) {
-            Uri localUri = Uri.parse(path);
-            path = localUri.getLastPathSegment();
-        } else {
-            path = uri.getLastPathSegment();
+        String printJobName = getLastPathSegment(uri);
+        if (printJobName == null) {
+            printJobName = DEFAULT_PRINT_JOB_NAME;
         }
         PrintHelper printer = new PrintHelper(this);
         try {
-            printer.printBitmap(path, uri);
+            printer.printBitmap(printJobName, uri);
         } catch (FileNotFoundException fnfe) {
             Log.e(TAG, "Error printing an image", fnfe);
+        } catch (RuntimeException e) {
+            Log.e(TAG,"Print failure,",e);
         }
     }
+
+    private String getLastPathSegment(Uri uri) {
+        if (uri == null) return null;
+        String path = null;
+        try {
+            path = ImageLoader.getLocalPathFromUri(this, uri);
+        } catch (IllegalArgumentException e) {
+            e.printStackTrace();
+        }
+
+        Uri localUri;
+        if (path != null) {
+            localUri = Uri.parse(path);
+        } else {
+            path = uri.getPath();
+            localUri = uri;
+        }
+
+        String lastPathSegment = localUri.getLastPathSegment();
+
+        // uri.getLastPathSegment will return null if localUri contains
+        // spacial characters such as ':', so use other way to get it.
+        if (lastPathSegment == null) {
+            // use substring to get last path segment.
+            int indexOfLastPathSegment = path.lastIndexOf("/") + 1;
+            lastPathSegment = path.substring(indexOfLastPathSegment, path.length());
+        }
+        return lastPathSegment;
+    }
+
+   public Toolbar getToolbar() {
+       return mToolbar;
+   }
+
+   public void setToolbar(Toolbar toolbar) {
+       mToolbar = toolbar ;
+   }
 }
diff --git a/src/com/android/gallery3d/app/AbstractPermissionActivity.java b/src/com/android/gallery3d/app/AbstractPermissionActivity.java
new file mode 100644
index 0000000..9e7e5ca
--- /dev/null
+++ b/src/com/android/gallery3d/app/AbstractPermissionActivity.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import androidx.fragment.app.FragmentActivity;
+
+import java.util.ArrayList;
+
+public abstract class AbstractPermissionActivity extends FragmentActivity {
+
+    public static final int PERMISSION_REQUEST_STORAGE = 1;
+    private boolean permissionGranted = false;
+
+    protected abstract void onGetPermissionsSuccess();
+    protected abstract void onGetPermissionsFailure();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestStoragePermission();
+    }
+
+    private void requestStoragePermission() {
+        String[] permissions = {
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.READ_EXTERNAL_STORAGE
+        };
+        requestPermission(permissions, PERMISSION_REQUEST_STORAGE);
+    }
+
+    protected void requestPermission(String[] permissions, int requestCode) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            permissionGranted = true;
+            return;
+        }
+
+        boolean needRequest = false;
+        ArrayList<String> permissionList = new ArrayList<String>();
+        for (String permission : permissions) {
+            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+                permissionList.add(permission);
+                needRequest = true;
+            }
+        }
+
+        if (needRequest) {
+            int count = permissionList.size();
+            if (count > 0) {
+                String[] permissionArray = new String[count];
+                for (int i = 0; i < count; i++) {
+                    permissionArray[i] = permissionList.get(i);
+                }
+
+                requestPermissions(permissionArray, requestCode);
+            }
+        }
+        permissionGranted = !needRequest;
+    }
+
+    private boolean checkPermissionGrantResults(int[] grantResults) {
+        for (int result : grantResults) {
+            if (result != PackageManager.PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+                                           int[] grantResults) {
+        permissionGranted = checkPermissionGrantResults(grantResults);
+        switch (requestCode) {
+            case PERMISSION_REQUEST_STORAGE: {
+                if (permissionGranted) {
+                    onGetPermissionsSuccess();
+                } else {
+                    onGetPermissionsFailure();
+                }
+            }
+        }
+    }
+
+    protected boolean isPermissionGranted() {
+        return permissionGranted;
+    }
+}
diff --git a/src/com/android/gallery3d/app/ActivityState.java b/src/com/android/gallery3d/app/ActivityState.java
index 2f1e0c9..7050db6 100644
--- a/src/com/android/gallery3d/app/ActivityState.java
+++ b/src/com/android/gallery3d/app/ActivityState.java
@@ -32,7 +32,7 @@
 import android.view.Window;
 import android.view.WindowManager;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.anim.StateTransitionAnimation;
 import com.android.gallery3d.glrenderer.RawTexture;
 import com.android.gallery3d.ui.GLView;
@@ -46,6 +46,7 @@
     protected static final int FLAG_SCREEN_ON_ALWAYS = 8;
     protected static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 16;
     protected static final int FLAG_SHOW_WHEN_LOCKED = 32;
+    protected static final int FLAG_SCREEN_FULL = 64;
 
     protected AbstractGalleryActivity mActivity;
     protected Bundle mData;
@@ -164,6 +165,12 @@
         } else {
             params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
         }
+
+        if (0 != (mFlags & FLAG_SCREEN_FULL)) {
+            params.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+        } else {
+            params.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
+        }
         win.setAttributes(params);
     }
 
@@ -205,9 +212,6 @@
                 actionBar.show();
             }
             int stateCount = mActivity.getStateManager().getStateCount();
-            mActivity.getGalleryActionBar().setDisplayOptions(stateCount > 1, true);
-            // Default behavior, this can be overridden in ActivityState's onResume.
-            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
         }
 
         activity.invalidateOptionsMenu();
diff --git a/src/com/android/gallery3d/app/AlbumDataLoader.java b/src/com/android/gallery3d/app/AlbumDataLoader.java
index 28a8228..b56304e 100644
--- a/src/com/android/gallery3d/app/AlbumDataLoader.java
+++ b/src/com/android/gallery3d/app/AlbumDataLoader.java
@@ -19,6 +19,8 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.Process;
+import android.text.TextUtils;
+import android.view.View;
 
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.ContentListener;
@@ -33,6 +35,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
+import java.util.Locale;
 
 public class AlbumDataLoader {
     @SuppressWarnings("unused")
@@ -119,7 +122,9 @@
     }
 
     public MediaItem get(int index) {
-        if (!isActive(index)) {
+        if (!isActive(index)
+                && View.LAYOUT_DIRECTION_LTR == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
             return mSource.getMediaItem(index, 1).get(0);
         }
         return mData[index % mData.length];
diff --git a/src/com/android/gallery3d/app/AlbumListViewPage.java b/src/com/android/gallery3d/app/AlbumListViewPage.java
new file mode 100644
index 0000000..a207cb9
--- /dev/null
+++ b/src/com/android/gallery3d/app/AlbumListViewPage.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+public class AlbumListViewPage extends AlbumPage {
+
+}
diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java
index 44f2404..4f3f348 100644
--- a/src/com/android/gallery3d/app/AlbumPage.java
+++ b/src/com/android/gallery3d/app/AlbumPage.java
@@ -19,19 +19,28 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+//import android.drm.DrmHelper;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
+import android.view.View;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.Toolbar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaDetails;
@@ -59,6 +68,8 @@
 import com.android.gallery3d.util.GalleryUtils;
 import com.android.gallery3d.util.MediaSetUtils;
 
+import java.util.ArrayList;
+import java.util.Locale;
 
 public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner,
         SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
@@ -72,6 +83,8 @@
     public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu";
     public static final String KEY_EMPTY_ALBUM = "empty-album";
     public static final String KEY_RESUME_ANIMATION = "resume_animation";
+    public static final String KEY_IS_VIDEOS_SCREEN = "is-videos-screen";
+    public static final String KEY_VIEWTYPE = "viewtype";
 
     private static final int REQUEST_SLIDESHOW = 1;
     public static final int REQUEST_PHOTO = 2;
@@ -82,6 +95,9 @@
 
     private static final float USER_DISTANCE_METER = 0.3f;
 
+    // Data cache size, equal to AlbumDataLoader.DATA_CACHE_SIZE
+    private static final int DATA_CACHE_SIZE = 256;
+
     private boolean mIsActive = false;
     private AlbumSlotRenderer mAlbumView;
     private Path mMediaSetPath;
@@ -93,7 +109,8 @@
     protected SelectionManager mSelectionManager;
 
     private boolean mGetContent;
-    private boolean mShowClusterMenu;
+    //private boolean mShowClusterMenu;
+    private boolean mIsVideoScreen;
 
     private ActionModeHandler mActionModeHandler;
     private int mFocusIndex = 0;
@@ -116,7 +133,23 @@
     private Handler mHandler;
     private static final int MSG_PICK_PHOTO = 0;
 
+    private Menu mActionMenu;
+
     private PhotoFallbackEffect mResumeEffect;
+
+    private Config.AlbumPage mConfig;
+    private Config.AlbumPageList mConfigList;
+    private GalleryActionBar mActionBar;
+
+    public static final int GRID_VIEW = 0;
+    public static final int LIST_VIEW = 1;
+    public static int mCurrentView = GRID_VIEW;
+    private final String PREF_VIEWTYPE = "albumview-type";
+    public boolean mViewType = true;
+    private Bundle mData;
+    private MenuItem mItemViewType;
+    private TextView tvEmptyAlbum;
+    private boolean mShowedEmptyToastForSelf;
     private PhotoFallbackEffect.PositionProvider mPositionProvider =
             new PhotoFallbackEffect.PositionProvider() {
         @Override
@@ -152,21 +185,45 @@
         protected void onLayout(
                 boolean changed, int left, int top, int right, int bottom) {
 
-            int slotViewTop = mActivity.getGalleryActionBar().getHeight();
-            int slotViewBottom = bottom - top;
-            int slotViewRight = right - left;
+            int paddingLeft;
+            int paddingBottom;
+            int paddingRight;
+            int paddingTop;
+
+            if (mViewType) {
+                paddingTop = mConfig.paddingLeft;
+                paddingLeft = mConfig.paddingLeft;
+            } else {
+                paddingTop = mConfigList.paddingLeft;
+                paddingLeft = mConfigList.paddingLeft;
+            }
+            paddingBottom = mConfig.paddingBottom;
+            paddingRight = mConfig.paddingRight;
+
+            int slotViewTop;
+            Toolbar toolbar = mActivity.getToolbar();
+            if (toolbar != null) {
+                slotViewTop = toolbar.getLayoutParams().height + paddingTop;
+            } else {
+                slotViewTop = mActivity.getGalleryActionBar().getHeight() + paddingTop;
+            }
+            int slotViewBottom = bottom - top - paddingBottom;
+            int slotViewRight = right - left - paddingRight;
+            int slotViewLeft = paddingLeft;
 
             if (mShowDetails) {
-                mDetailsHelper.layout(left, slotViewTop, right, bottom);
+                mDetailsHelper.layout(slotViewLeft, slotViewTop, slotViewRight, slotViewBottom);
             } else {
                 mAlbumView.setHighlightItemPath(null);
             }
 
             // Set the mSlotView as a reference point to the open animation
             mOpenCenter.setReferencePosition(0, slotViewTop);
-            mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
-            GalleryUtils.setViewPointMatrix(mMatrix,
-                    (right - left) / 2, (bottom - top) / 2, -mUserDistance);
+            mSlotView.layout(slotViewLeft, slotViewTop, slotViewRight,
+                    slotViewBottom);
+
+            GalleryUtils.setViewPointMatrix(mMatrix, (right - left) / 2,
+                    (bottom - top) / 2, -mUserDistance);
         }
 
         @Override
@@ -206,6 +263,8 @@
             hideDetails();
         } else if (mSelectionManager.inSelectionMode()) {
             mSelectionManager.leaveSelectionMode();
+        } else if (mIsVideoScreen) {
+            super.onBackPressed();
         } else {
             if(mLaunchedFromPhotoPage) {
                 mActivity.getTransitionStore().putIfNotPresent(
@@ -226,6 +285,10 @@
         if (mInCameraApp) {
             GalleryUtils.startGalleryActivity(mActivity);
         } else if (mActivity.getStateManager().getStateCount() > 1) {
+            Toolbar toolbar = mActivity.getToolbar();
+            if (toolbar != null) {
+                ((GalleryActivity) mActivity).toggleNavBar(true);
+            }
             super.onBackPressed();
         } else if (mParentMediaSetString != null) {
             Bundle data = new Bundle(getData());
@@ -278,10 +341,31 @@
         }
 
         MediaItem item = mAlbumDataAdapter.get(slotIndex);
-        if (item == null) return; // Item not ready yet, ignore the click
+
+        // Checking it is RTL or not
+        boolean isLayoutRtl = (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) ? true : false;
+
+        // When not RTL, return directly to ignore the click
+        if (!isLayoutRtl && item == null) {
+            return;
+        }
+
         if (mGetContent) {
+            if (isLayoutRtl && item == null) {
+                return; // Item not ready yet, ignore the click
+            }
+//            if (DrmHelper.isDrmFile(DrmHelper.getFilePath(
+//                    mActivity.getAndroidContext(), item.getContentUri()))) {
+//                Toast.makeText(mActivity, R.string.no_permission_for_drm,
+//                        Toast.LENGTH_SHORT).show();
+//                return;
+//            }
             onGetContent(item);
         } else if (mLaunchedFromPhotoPage) {
+            if (isLayoutRtl && item == null) {
+                return; // Item not ready yet, ignore the click
+            }
             TransitionStore transitions = mActivity.getTransitionStore();
             transitions.put(
                     PhotoPage.KEY_ALBUMPAGE_TRANSITION,
@@ -297,13 +381,18 @@
                     mSlotView.getSlotRect(slotIndex, mRootPane));
             data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
                     mMediaSetPath.toString());
-            data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
-                    item.getPath().toString());
+
+            // Item not ready yet, don't pass the photo path to bundle
+            if (!isLayoutRtl && item != null) {
+                data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
+                        item.getPath().toString());
+            }
             data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION,
                     PhotoPage.MSG_ALBUMPAGE_STARTED);
             data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP,
                     startInFilmstrip);
             data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll());
+            data.putBoolean(PhotoPage.KEY_FROM_VIDEOS_SCREEN, mIsVideoScreen);
             if (startInFilmstrip) {
                 mActivity.getStateManager().switchState(this, FilmstripPage.class, data);
             } else {
@@ -349,14 +438,6 @@
         String newPath = FilterUtils.newClusterPath(basePath, clusterType);
         Bundle data = new Bundle(getData());
         data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
-        if (mShowClusterMenu) {
-            Context context = mActivity.getAndroidContext();
-            data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName());
-            data.putString(AlbumSetPage.KEY_SET_SUBTITLE,
-                    GalleryActionBar.getClusterByTypeString(context, clusterType));
-        }
-
-        // mAlbumView.savePositions(PositionRepository.getInstance(mActivity));
         mActivity.getStateManager().startStateForResult(
                 AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
     }
@@ -365,12 +446,17 @@
     protected void onCreate(Bundle data, Bundle restoreState) {
         super.onCreate(data, restoreState);
         mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER);
+        mCurrentView = GalleryUtils.getIntPref(mActivity, PREF_VIEWTYPE,
+                GRID_VIEW);
+        mViewType = mCurrentView == GRID_VIEW;
+        mData = data;
         initializeViews();
         initializeData(data);
         mGetContent = data.getBoolean(GalleryActivity.KEY_GET_CONTENT, false);
-        mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false);
+        mIsVideoScreen = data.getBoolean(KEY_IS_VIDEOS_SCREEN, false);
         mDetailsSource = new MyDetailsSource();
         Context context = mActivity.getAndroidContext();
+        mActionBar = mActivity.getGalleryActionBar();
 
         if (data.getBoolean(KEY_AUTO_SELECT_ALL)) {
             mSelectionManager.selectAll();
@@ -409,14 +495,6 @@
 
         setContentPane(mRootPane);
 
-        boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) |
-                mParentMediaSetString != null;
-        GalleryActionBar actionBar = mActivity.getGalleryActionBar();
-        actionBar.setDisplayOptions(enableHomeButton, false);
-        if (!mGetContent) {
-            actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this);
-        }
-
         // Set the reload bit here to prevent it exit this page in clearLoadingBit().
         setLoadingBit(BIT_LOADING_RELOAD);
         mLoadingFailed = false;
@@ -437,23 +515,18 @@
         super.onPause();
         mIsActive = false;
 
-        if (mSelectionManager.inSelectionMode()) {
-            mSelectionManager.leaveSelectionMode();
-        }
         mAlbumView.setSlotFilter(null);
         mActionModeHandler.pause();
         mAlbumDataAdapter.pause();
         mAlbumView.pause();
         DetailsHelper.pause();
-        if (!mGetContent) {
-            mActivity.getGalleryActionBar().disableAlbumModeMenu(true);
-        }
 
         if (mSyncTask != null) {
             mSyncTask.cancel();
             mSyncTask = null;
             clearLoadingBit(BIT_LOADING_SYNC);
         }
+        hideEmptyAlbumToast();
     }
 
     @Override
@@ -468,10 +541,18 @@
     private void initializeViews() {
         mSelectionManager = new SelectionManager(mActivity, false);
         mSelectionManager.setSelectionListener(this);
-        Config.AlbumPage config = Config.AlbumPage.get(mActivity);
-        mSlotView = new SlotView(mActivity, config.slotViewSpec);
-        mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
-                mSelectionManager, config.placeholderColor);
+        mConfig = Config.AlbumPage.get(mActivity);
+        mConfigList = Config.AlbumPageList.get(mActivity);
+        if (mViewType) {
+            mSlotView = new SlotView(mActivity, mConfig.slotViewSpec);
+            mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
+                    mConfig.labelSpec, mSelectionManager, mConfig.placeholderColor, mViewType);
+        } else {
+            mSlotView = new SlotView(mActivity, mConfigList.slotViewSpec);
+            mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView,
+                    mConfigList.labelSpec, mSelectionManager,
+                    mConfig.placeholderColor, mViewType);
+        }
         mSlotView.setSlotRenderer(mAlbumView);
         mRootPane.addComponent(mSlotView);
         mSlotView.setListener(new SlotView.SimpleListener() {
@@ -540,26 +621,57 @@
 
     @Override
     protected boolean onCreateActionBar(Menu menu) {
-        GalleryActionBar actionBar = mActivity.getGalleryActionBar();
+        mActionMenu = menu;
+        //GalleryActionBar actionBar = mActivity.getGalleryActionBar();
         MenuInflater inflator = getSupportMenuInflater();
         if (mGetContent) {
             inflator.inflate(R.menu.pickup, menu);
             int typeBits = mData.getInt(GalleryActivity.KEY_TYPE_BITS,
                     DataManager.INCLUDE_IMAGE);
-            actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
+            mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
         } else {
             inflator.inflate(R.menu.album, menu);
-            actionBar.setTitle(mMediaSet.getName());
+            mActionBar.setTitle(mMediaSet.getName());
 
-            FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
+            FilterUtils.setupMenuItems(mActionBar, mMediaSetPath, true);
 
-            menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
             menu.findItem(R.id.action_camera).setVisible(
-                    MediaSetUtils.isCameraSource(mMediaSetPath)
-                    && GalleryUtils.isCameraAvailable(mActivity));
+                   GalleryUtils.isAnyCameraAvailable(mActivity));
+            menu.findItem(R.id.action_slideshow).setVisible(!mIsVideoScreen);
+            MenuItem item = menu.findItem(R.id.action_view_type);
+            updateMenuTitle(item);
+            updateMenuTitle(menu.findItem(R.id.action_select));
 
         }
-        actionBar.setSubtitle(null);
+        //actionBar.setSubtitle(null);
+        // remove slideshow if all are videos
+        if (allVideoFiles() && !mGetContent){
+            menu.findItem(R.id.action_slideshow).setVisible(false);
+        }
+        return true;
+    }
+
+    private boolean allVideoFiles() {
+        if (mMediaSet == null)
+            return false;
+        int count = mMediaSet.getMediaItemCount();
+        ArrayList<MediaItem> list;
+        MediaItem item;
+        for (int i = 0; i < count; i++) {
+            list = mMediaSet.getMediaItem(i, 1);
+            if (list == null) {
+                continue;
+            }
+            if (list.isEmpty()) {
+                break;
+            }
+            item = list.get(0);
+            if (item == null) {
+                continue;
+            }
+            if (item.getMimeType().trim().startsWith("image/"))
+                return false;
+        }
         return true;
     }
 
@@ -574,8 +686,17 @@
     }
 
     private void switchToFilmstrip() {
-        if (mAlbumDataAdapter.size() < 1) return;
+        // Invalid album, return back directly.
+        if (mAlbumDataAdapter.size() < 1) {
+            return;
+        }
+
         int targetPhoto = mSlotView.getVisibleStart();
+        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) {
+            // Fetch corresponding index from another side, only in RTL
+            targetPhoto = mAlbumDataAdapter.size() - targetPhoto - 1;
+        }
         prepareAnimationBackToFilmstrip(targetPhoto);
         if(mLaunchedFromPhotoPage) {
             onBackPressed();
@@ -598,10 +719,6 @@
                 mSelectionManager.setAutoLeaveSelectionMode(false);
                 mSelectionManager.enterSelectionMode();
                 return true;
-            case R.id.action_group_by: {
-                mActivity.getGalleryActionBar().showClusterDialog(this);
-                return true;
-            }
             case R.id.action_slideshow: {
                 mInCameraAndWantQuitOnPause = false;
                 Bundle data = new Bundle();
@@ -624,6 +741,10 @@
                 GalleryUtils.startCameraActivity(mActivity);
                 return true;
             }
+            case R.id.action_view_type: {
+            switchView();
+            return true;
+            }
             default:
                 return false;
         }
@@ -642,7 +763,22 @@
             case REQUEST_PHOTO: {
                 if (data == null) return;
                 mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    // Fetch corresponding index from another side, only in RTL
+                    mFocusIndex = mAlbumDataAdapter.size() - mFocusIndex - 1;
+                    // Prepare to jump to mFocusIndex position, only enabled in RTL
+                    mSlotView.setIsFromPhotoPage(true);
+                }
+
+                // Let picture of mFocusIndex visible
                 mSlotView.makeSlotVisible(mFocusIndex);
+
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    // Reset variable
+                    mSlotView.setIsFromPhotoPage(false);
+                }
                 break;
             }
             case REQUEST_DO_ANIMATION: {
@@ -652,17 +788,28 @@
         }
     }
 
+    private void updateMenuItem() {
+        if (allVideoFiles() && !mGetContent) {
+            mActionMenu.findItem(R.id.action_slideshow).setVisible(false);
+        }
+    }
+
     @Override
     public void onSelectionModeChange(int mode) {
         switch (mode) {
             case SelectionManager.ENTER_SELECTION_MODE: {
                 mActionModeHandler.startActionMode();
                 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                ((GalleryActivity) mActivity).toggleNavBar(false);
                 break;
             }
             case SelectionManager.LEAVE_SELECTION_MODE: {
                 mActionModeHandler.finishActionMode();
+                if (mActivity.getStateManager().getStateCount() <= 1) {
+                    ((GalleryActivity) mActivity).toggleNavBar(true);
+                }
                 mRootPane.invalidate();
+                updateMenuItem();
                 break;
             }
             case SelectionManager.SELECT_ALL_MODE: {
@@ -726,12 +873,24 @@
         mLoadingBits &= ~loadTaskBit;
         if (mLoadingBits == 0 && mIsActive) {
             if (mAlbumDataAdapter.size() == 0) {
-                Intent result = new Intent();
-                result.putExtra(KEY_EMPTY_ALBUM, true);
-                setStateResult(Activity.RESULT_OK, result);
-                mActivity.getStateManager().finishState(this);
+                if (mIsVideoScreen) {
+                    mShowedEmptyToastForSelf = true;
+                    showEmptyAlbumToast(Toast.LENGTH_LONG);
+                } else {
+                    Intent result = new Intent();
+                    result.putExtra(KEY_EMPTY_ALBUM, true);
+                    setStateResult(Activity.RESULT_OK, result);
+                    mActivity.getStateManager().finishState(this);
+                }
+                return;
+            } else {
+                hideEmptyAlbumToast();
             }
         }
+        if (mShowedEmptyToastForSelf && mIsVideoScreen) {
+            mShowedEmptyToastForSelf = false;
+            hideEmptyAlbumToast();
+        }
     }
 
     private class MyLoadingListener implements LoadingListener {
@@ -783,4 +942,53 @@
             switchToFilmstrip();
         }
     }
+
+    public void updateMenuTitle(MenuItem item) {
+        if (item.getItemId() == R.id.action_view_type) {
+            item.setTitle(mViewType ? R.string.action_viewtype_list
+                    : R.string.action_viewtype_grid);
+        } else if (item.getItemId() == R.id.action_select) {
+            item.setTitle(mIsVideoScreen ? R.string.select_video : R.string.select_item);
+        }
+    }
+
+    private void switchView() {
+        if (mViewType) {
+            mCurrentView = LIST_VIEW;
+            GalleryUtils.setIntPref(mActivity, PREF_VIEWTYPE, mCurrentView);
+            mActivity.getStateManager().switchState(this,
+            AlbumListViewPage.class, mData);
+        } else {
+            mCurrentView = GRID_VIEW;
+            GalleryUtils.setIntPref(mActivity, PREF_VIEWTYPE, mCurrentView);
+            mActivity.getStateManager().switchState(this, AlbumPage.class,
+            mData);
+       }
+
+    }
+
+
+    private void showEmptyAlbumToast(int toastLength) {
+        RelativeLayout galleryRoot = (RelativeLayout) mActivity.findViewById(R.id.gallery_root);
+        if (galleryRoot == null) return;
+        if (tvEmptyAlbum == null) {
+            tvEmptyAlbum = new TextView(mActivity);
+            tvEmptyAlbum.setText(R.string.tvEmptyVideos);
+            tvEmptyAlbum.setTextColor(Color.parseColor("#8A000000"));
+            tvEmptyAlbum.setGravity(Gravity.CENTER);
+            tvEmptyAlbum.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
+            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+            galleryRoot.addView(tvEmptyAlbum, lp);
+        }
+        tvEmptyAlbum.setVisibility(View.VISIBLE);
+    }
+
+    private void hideEmptyAlbumToast() {
+        if (tvEmptyAlbum != null) {
+            tvEmptyAlbum.setVisibility(View.GONE);
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/app/AlbumPicker.java b/src/com/android/gallery3d/app/AlbumPicker.java
index 8c2d09a..729585e 100644
--- a/src/com/android/gallery3d/app/AlbumPicker.java
+++ b/src/com/android/gallery3d/app/AlbumPicker.java
@@ -19,7 +19,7 @@
 import android.content.Intent;
 import android.os.Bundle;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.data.DataManager;
 
 public class AlbumPicker extends PickerActivity {
diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java
old mode 100644
new mode 100755
index 909d910..e52b433
--- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java
+++ b/src/com/android/gallery3d/app/AlbumSetDataLoader.java
@@ -28,6 +28,7 @@
 import com.android.gallery3d.data.Path;
 import com.android.gallery3d.ui.SynchronizedHandler;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -66,7 +67,7 @@
     private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
     private int mSize;
 
-    private DataListener mDataListener;
+    private ArrayList<DataListener> mDataListener = new ArrayList<>();
     private LoadingListener mLoadingListener;
     private ReloadTask mReloadTask;
 
@@ -224,7 +225,11 @@
     }
 
     public void setModelListener(DataListener listener) {
-        mDataListener = listener;
+        mDataListener.add(listener);
+    }
+
+    public void removeModelListener(DataListener listener) {
+        mDataListener.remove(listener);
     }
 
     public void setLoadingListener(LoadingListener listener) {
@@ -287,7 +292,10 @@
             mSourceVersion = info.version;
             if (mSize != info.size) {
                 mSize = info.size;
-                if (mDataListener != null) mDataListener.onSizeChanged(mSize);
+                if (mDataListener != null)
+                    for (DataListener l : mDataListener) {
+                        l.onSizeChanged(mSize);
+                    }
                 if (mContentEnd > mSize) mContentEnd = mSize;
                 if (mActiveEnd > mSize) mActiveEnd = mSize;
             }
@@ -303,7 +311,9 @@
                 mTotalCount[pos] = info.totalCount;
                 if (mDataListener != null
                         && info.index >= mActiveStart && info.index < mActiveEnd) {
-                    mDataListener.onContentChanged(info.index);
+                    for (DataListener l : mDataListener) {
+                        l.onContentChanged(info.index);
+                    }
                 }
             }
             return null;
diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java
old mode 100644
new mode 100755
index d56b5b8..7eaa2bc
--- a/src/com/android/gallery3d/app/AlbumSetPage.java
+++ b/src/com/android/gallery3d/app/AlbumSetPage.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,10 +22,14 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -31,9 +38,10 @@
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.RelativeLayout;
+import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaDetails;
@@ -118,6 +126,7 @@
 
     private Button mCameraButton;
     private boolean mShowedEmptyToastForSelf = false;
+    private TextView tvEmptyAlbum;
 
     @Override
     protected int getBackgroundColorId() {
@@ -132,17 +141,44 @@
                 boolean changed, int left, int top, int right, int bottom) {
             mEyePosition.resetPosition();
 
-            int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop;
-            int slotViewBottom = bottom - top - mConfig.paddingBottom;
-            int slotViewRight = right - left;
+            int paddingLeft;
+            int paddingBottom;
+            int paddingRight;
+            int paddingTop;
+
+            if (right - left > bottom - top) {
+                paddingTop = mConfig.paddingTopLand;
+                paddingBottom = mConfig.paddingBottomLand;
+                paddingRight = mConfig.paddingRightLand;
+                paddingLeft = mConfig.paddingLeftLand;
+            }
+            else
+            {
+                paddingTop = mConfig.paddingTop;
+                paddingBottom = mConfig.paddingBottom;
+                paddingRight = mConfig.paddingRight;
+                paddingLeft = mConfig.paddingLeft;
+            }
+
+            int slotViewTop;
+            android.widget.Toolbar toolbar = mActivity.getToolbar();
+            if (toolbar != null) {
+                slotViewTop = toolbar.getLayoutParams().height + paddingTop;
+            } else {
+                slotViewTop = mActivity.getGalleryActionBar().getHeight() + paddingTop;
+            }
+            int slotViewBottom = bottom - top - paddingBottom;
+            int slotViewRight = right - left - paddingRight;
+            int slotViewLeft = paddingLeft ;
+
 
             if (mShowDetails) {
-                mDetailsHelper.layout(left, slotViewTop, right, bottom);
+                mDetailsHelper.layout(slotViewLeft, slotViewTop, slotViewRight, slotViewBottom);
             } else {
                 mAlbumSetView.setHighlightItemPath(null);
             }
 
-            mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom);
+            mSlotView.layout(slotViewLeft, slotViewTop, slotViewRight, slotViewBottom);
         }
 
         @Override
@@ -214,27 +250,41 @@
     WeakReference<Toast> mEmptyAlbumToast = null;
 
     private void showEmptyAlbumToast(int toastLength) {
-        Toast toast;
-        if (mEmptyAlbumToast != null) {
-            toast = mEmptyAlbumToast.get();
-            if (toast != null) {
-                toast.show();
-                return;
-            }
+        //CRs-Fixed:951767 java.lang.NullPointerException: Attempt to invoke virtual method
+        // 'void android.widget.RelativeLayout.addView(android.view.View
+        RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity)
+                .findViewById(R.id.gallery_root);
+        if (galleryRoot == null) return ;
+        if (tvEmptyAlbum == null) {
+            tvEmptyAlbum = new TextView(mActivity);
+            tvEmptyAlbum.setText(R.string.tvEmptyAlbum);
+            tvEmptyAlbum.setTextColor(Color.parseColor("#8A000000"));
+            tvEmptyAlbum.setGravity(Gravity.CENTER);
+            tvEmptyAlbum.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
+            tvEmptyAlbum.setId(R.id.empty_album);
+            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+            galleryRoot.addView(tvEmptyAlbum, lp);
         }
-        toast = Toast.makeText(mActivity, R.string.empty_album, toastLength);
-        mEmptyAlbumToast = new WeakReference<Toast>(toast);
-        toast.show();
+        tvEmptyAlbum.setVisibility(View.VISIBLE);
     }
 
     private void hideEmptyAlbumToast() {
-        if (mEmptyAlbumToast != null) {
-            Toast toast = mEmptyAlbumToast.get();
-            if (toast != null) toast.cancel();
+        if (tvEmptyAlbum != null) {
+            tvEmptyAlbum.setVisibility(View.GONE);
         }
     }
 
     private void pickAlbum(int slotIndex) {
+        if (mActivity.getStateManager().getStateCount() >= 1) {
+            android.widget.Toolbar toolbar = mActivity.getToolbar();
+            if (toolbar != null) {
+                ((GalleryActivity) mActivity).toggleNavBar(false);
+            }
+        }
+
         if (!mIsActive) return;
 
         MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex);
@@ -268,10 +318,10 @@
                 data.putInt(PhotoPage.KEY_INDEX_HINT, 0);
                 data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
                         mediaPath);
-                data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, true);
+                data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, false);
                 data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetSet.isCameraRoll());
                 mActivity.getStateManager().startStateForResult(
-                        FilmstripPage.class, AlbumPage.REQUEST_PHOTO, data);
+                        SinglePhotoPage.class, AlbumPage.REQUEST_PHOTO, data);
                 return;
             }
             data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath);
@@ -329,9 +379,8 @@
         mEyePosition = new EyePosition(context, this);
         mDetailsSource = new MyDetailsSource();
         mActionBar = mActivity.getGalleryActionBar();
-        mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE,
-                FilterUtils.CLUSTER_BY_ALBUM);
-
+        //mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE,
+        //        FilterUtils.CLUSTER_BY_ALBUM);
         mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
             @Override
             public void handleMessage(Message message) {
@@ -371,8 +420,14 @@
         RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                 RelativeLayout.LayoutParams.WRAP_CONTENT,
                 RelativeLayout.LayoutParams.WRAP_CONTENT);
-        lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+        if (tvEmptyAlbum != null && tvEmptyAlbum.getVisibility() == View.VISIBLE) {
+            lp.addRule(RelativeLayout.BELOW, tvEmptyAlbum.getId());
+            lp.addRule(RelativeLayout.CENTER_HORIZONTAL);
+        } else {
+            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+        }
         galleryRoot.addView(mCameraButton, lp);
+
         return true;
     }
 
@@ -385,11 +440,6 @@
         mCameraButton = null;
     }
 
-    private void showCameraButton() {
-        if (mCameraButton == null && !setupCameraButton()) return;
-        mCameraButton.setVisibility(View.VISIBLE);
-    }
-
     private void hideCameraButton() {
         if (mCameraButton == null) return;
         mCameraButton.setVisibility(View.GONE);
@@ -412,9 +462,11 @@
                     mShowedEmptyToastForSelf = true;
                     showEmptyAlbumToast(Toast.LENGTH_LONG);
                     mSlotView.invalidate();
-                    showCameraButton();
                 }
                 return;
+            } else {
+                hideEmptyAlbumToast();
+                hideCameraButton();
             }
         }
         // Hide the empty album toast if we are in the root instance of
@@ -443,7 +495,7 @@
         // Call disableClusterMenu to avoid receiving callback after paused.
         // Don't hide menu here otherwise the list menu will disappear earlier than
         // the action bar, which is janky and unwanted behavior.
-        mActionBar.disableClusterMenu(false);
+        //mActionBar.disableClusterMenu(false);
         if (mSyncTask != null) {
             mSyncTask.cancel();
             mSyncTask = null;
@@ -464,9 +516,9 @@
         mAlbumSetView.resume();
         mEyePosition.resume();
         mActionModeHandler.resume();
-        if (mShowClusterMenu) {
+        /*if (mShowClusterMenu) {
             mActionBar.enableClusterMenu(mSelectedAction, this);
-        }
+        }*/
         if (!mInitialSynced) {
             setLoadingBit(BIT_LOADING_SYNC);
             mSyncTask = mMediaSet.requestSync(AlbumSetPage.this);
@@ -479,6 +531,7 @@
         mSelectionManager.setSourceMediaSet(mMediaSet);
         mAlbumSetDataAdapter = new AlbumSetDataLoader(
                 mActivity, mMediaSet, DATA_CACHE_SIZE);
+        mSelectionManager.setAlbumSetDataLoader(mAlbumSetDataAdapter);
         mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener());
         mAlbumSetView.setModel(mAlbumSetDataAdapter);
     }
@@ -543,14 +596,21 @@
             inflater.inflate(R.menu.albumset, menu);
             boolean wasShowingClusterMenu = mShowClusterMenu;
             mShowClusterMenu = !inAlbum;
-            boolean selectAlbums = !inAlbum &&
-                    mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
+           /*if (mShowClusterMenu != wasShowingClusterMenu) {
+                if (mShowClusterMenu) {
+                    mActionBar.enableClusterMenu(mSelectedAction, this);
+                } else {
+                    mActionBar.disableClusterMenu(true);
+                }
+            }*/
+            boolean selectAlbums = !inAlbum ;// &&
+                   // mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM;
             MenuItem selectItem = menu.findItem(R.id.action_select);
             selectItem.setTitle(activity.getString(
                     selectAlbums ? R.string.select_album : R.string.select_group));
 
             MenuItem cameraItem = menu.findItem(R.id.action_camera);
-            cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity));
+            cameraItem.setVisible(GalleryUtils.isAnyCameraAvailable(activity));
 
             FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false);
 
@@ -560,15 +620,10 @@
             helpItem.setVisible(helpIntent != null);
             if (helpIntent != null) helpItem.setIntent(helpIntent);
 
-            mActionBar.setTitle(mTitle);
-            mActionBar.setSubtitle(mSubtitle);
-            if (mShowClusterMenu != wasShowingClusterMenu) {
-                if (mShowClusterMenu) {
-                    mActionBar.enableClusterMenu(mSelectedAction, this);
-                } else {
-                    mActionBar.disableClusterMenu(true);
-                }
-            }
+            MenuItem moreItem = menu.findItem(R.id.action_more_image);
+            moreItem.setVisible(mActivity.getResources().getBoolean(
+                    R.bool.config_show_more_images));
+            mActionBar.setTitle(R.string.albums_title);
         }
         return true;
     }
@@ -577,6 +632,11 @@
     protected boolean onItemSelected(MenuItem item) {
         Activity activity = mActivity;
         switch (item.getItemId()) {
+            case R.id.action_more_image:
+                Uri moreUri = Uri.parse(mActivity.getString(R.string.website_for_more_image));
+                Intent moreIntent = new Intent(Intent.ACTION_VIEW, moreUri);
+                mActivity.startActivity(moreIntent);
+                return true;
             case R.id.action_cancel:
                 activity.setResult(Activity.RESULT_CANCELED);
                 activity.finish();
@@ -610,14 +670,10 @@
                 mActivity.getStateManager().startState(ManageCachePage.class, data);
                 return true;
             }
-            case R.id.action_sync_picasa_albums: {
-                PicasaSource.requestSync(activity);
-                return true;
-            }
-            case R.id.action_settings: {
+            /*case R.id.action_settings: {
                 activity.startActivity(new Intent(activity, GallerySettings.class));
                 return true;
-            }
+            }*/
             default:
                 return false;
         }
@@ -635,7 +691,7 @@
         }
     }
 
-    private String getSelectedString() {
+    /*private String getSelectedString() {
         int count = mSelectionManager.getSelectedCount();
         int action = mActionBar.getClusterTypeAction();
         int string = action == FilterUtils.CLUSTER_BY_ALBUM
@@ -643,22 +699,24 @@
                 : R.plurals.number_of_groups_selected;
         String format = mActivity.getResources().getQuantityString(string, count);
         return String.format(format, count);
-    }
+    }*/
 
     @Override
     public void onSelectionModeChange(int mode) {
         switch (mode) {
             case SelectionManager.ENTER_SELECTION_MODE: {
-                mActionBar.disableClusterMenu(true);
+                //mActionBar.disableClusterMenu(true);
                 mActionModeHandler.startActionMode();
                 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                ((GalleryActivity) mActivity).toggleNavBar(false);
                 break;
             }
             case SelectionManager.LEAVE_SELECTION_MODE: {
                 mActionModeHandler.finishActionMode();
-                if (mShowClusterMenu) {
+                ((GalleryActivity) mActivity).toggleNavBar(true);
+                /*if (mShowClusterMenu) {
                     mActionBar.enableClusterMenu(mSelectedAction, this);
-                }
+                }*/
                 mRootPane.invalidate();
                 break;
             }
@@ -672,7 +730,7 @@
 
     @Override
     public void onSelectionChange(Path path, boolean selected) {
-        mActionModeHandler.setTitle(getSelectedString());
+//        mActionModeHandler.setTitle(getSelectedString());
         mActionModeHandler.updateSupportedOperation(path, selected);
     }
 
diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java
index 9adb4e7..f4fbeb8 100644
--- a/src/com/android/gallery3d/app/CommonControllerOverlay.java
+++ b/src/com/android/gallery3d/app/CommonControllerOverlay.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -32,7 +34,7 @@
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 /**
  * The common playback controller for the Movie Player or Video Trimming.
@@ -47,10 +49,13 @@
         PAUSED,
         ENDED,
         ERROR,
-        LOADING
+        LOADING,
+        BUFFERING,
+        RETRY_CONNECTING,
+        RETRY_CONNECTING_ERROR
     }
 
-    private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
+    protected static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6;
 
     protected Listener mListener;
 
@@ -96,20 +101,22 @@
         ProgressBar spinner = new ProgressBar(context);
         spinner.setIndeterminate(true);
         mLoadingView.addView(spinner, wrapContent);
-        TextView loadingText = createOverlayTextView(context);
-        loadingText.setText(R.string.loading_video);
-        mLoadingView.addView(loadingText, wrapContent);
         addView(mLoadingView, wrapContent);
 
         mPlayPauseReplayView = new ImageView(context);
-        mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play);
         mPlayPauseReplayView.setContentDescription(
                 context.getResources().getString(R.string.accessibility_play_video));
-        mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
         mPlayPauseReplayView.setScaleType(ScaleType.CENTER);
         mPlayPauseReplayView.setFocusable(true);
         mPlayPauseReplayView.setClickable(true);
         mPlayPauseReplayView.setOnClickListener(this);
+        TypedArray array = context.getTheme().obtainStyledAttributes(new int[] {
+                android.R.attr.actionBarItemBackground
+        });
+        Drawable drawable = array.getDrawable(array.getIndex(0));
+        if (drawable != null) {
+            mPlayPauseReplayView.setBackground(drawable);
+        }
         addView(mPlayPauseReplayView, wrapContent);
 
         mErrorView = createOverlayTextView(context);
@@ -119,7 +126,6 @@
                 new RelativeLayout.LayoutParams(
                         LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
         setLayoutParams(params);
-        hide();
     }
 
     abstract protected void createTimeBar(Context context);
@@ -252,7 +258,7 @@
     // | Navigation Bar | insets.bottom
     // +-----------------+/
     // Please see View.fitSystemWindows() for more details.
-    private final Rect mWindowInsets = new Rect();
+    protected final Rect mWindowInsets = new Rect();
 
     @Override
     protected boolean fitSystemWindows(Rect insets) {
@@ -290,7 +296,7 @@
         }
     }
 
-    private void layoutCenteredView(View view, int l, int t, int r, int b) {
+    protected void layoutCenteredView(View view, int l, int t, int r, int b) {
         int cw = view.getMeasuredWidth();
         int ch = view.getMeasuredHeight();
         int cl = (r - l - cw) / 2;
diff --git a/src/com/android/gallery3d/app/Config.java b/src/com/android/gallery3d/app/Config.java
index 7183acc..5a458ae 100644
--- a/src/com/android/gallery3d/app/Config.java
+++ b/src/com/android/gallery3d/app/Config.java
@@ -19,9 +19,12 @@
 import android.content.Context;
 import android.content.res.Resources;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ui.AlbumSetSlotRenderer;
+import com.android.gallery3d.ui.AlbumSlotRenderer;
 import com.android.gallery3d.ui.SlotView;
+import com.android.gallery3d.ui.TimeLineSlotRenderer;
+import com.android.gallery3d.ui.TimeLineSlotView;
 
 final class Config {
     public static class AlbumSetPage {
@@ -32,6 +35,12 @@
         public int paddingTop;
         public int paddingBottom;
         public int placeholderColor;
+        public int paddingLeft;
+        public int paddingRight;
+        public int paddingTopLand;
+        public int paddingBottomLand;
+        public int paddingLeftLand;
+        public int paddingRightLand;
 
         public static synchronized AlbumSetPage get(Context context) {
             if (sInstance == null) {
@@ -46,21 +55,34 @@
             placeholderColor = r.getColor(R.color.albumset_placeholder);
 
             slotViewSpec = new SlotView.Spec();
-            slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land);
-            slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port);
+            //slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land);
+            //slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port);
+            slotViewSpec.colsLand = r.getInteger(R.integer.albumset_cols_land);
+            slotViewSpec.colsPort = r.getInteger(R.integer.albumset_cols_port);
             slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.albumset_slot_gap);
+            slotViewSpec.slotGapLand = r.getDimensionPixelSize(R.dimen.albumset_slot_gap_land);
             slotViewSpec.slotHeightAdditional = 0;
+            slotViewSpec.slotWidth = r.getDimensionPixelSize(R.dimen.slot_width);
+            slotViewSpec.slotHeight = r.getDimensionPixelSize(R.dimen.slot_height);
 
             paddingTop = r.getDimensionPixelSize(R.dimen.albumset_padding_top);
             paddingBottom = r.getDimensionPixelSize(R.dimen.albumset_padding_bottom);
+            paddingLeft = r.getDimensionPixelSize(R.dimen.albumset_padding_left);
+            paddingRight = r.getDimensionPixelSize(R.dimen.albumset_padding_right);
+
+            paddingTopLand = r.getDimensionPixelSize(R.dimen.albumset_padding_top_land);
+            paddingBottomLand = r.getDimensionPixelSize(R.dimen.albumset_padding_bottom_land);
+
+            paddingLeftLand = r.getDimensionPixelSize(R.dimen.albumset_padding_left_land);
+            paddingRightLand = r.getDimensionPixelSize(R.dimen.albumset_padding_right_land);
 
             labelSpec = new AlbumSetSlotRenderer.LabelSpec();
             labelSpec.labelBackgroundHeight = r.getDimensionPixelSize(
                     R.dimen.albumset_label_background_height);
-            labelSpec.titleOffset = r.getDimensionPixelSize(
+            /*labelSpec.titleOffset = r.getDimensionPixelSize(
                     R.dimen.albumset_title_offset);
             labelSpec.countOffset = r.getDimensionPixelSize(
-                    R.dimen.albumset_count_offset);
+                    R.dimen.albumset_count_offset);*/
             labelSpec.titleFontSize = r.getDimensionPixelSize(
                     R.dimen.albumset_title_font_size);
             labelSpec.countFontSize = r.getDimensionPixelSize(
@@ -69,8 +91,12 @@
                     R.dimen.albumset_left_margin);
             labelSpec.titleRightMargin = r.getDimensionPixelSize(
                     R.dimen.albumset_title_right_margin);
-            labelSpec.iconSize = r.getDimensionPixelSize(
-                    R.dimen.albumset_icon_size);
+            labelSpec.titleLeftMargin = r.getDimensionPixelSize(
+                    R.dimen.albumset_title_left_margin);
+            labelSpec.countRightMargin = r.getDimensionPixelSize(
+                    R.dimen.albumset_count_right_margin);
+            /*labelSpec.iconSize = r.getDimensionPixelSize(
+                    R.dimen.albumset_icon_size);*/
             labelSpec.backgroundColor = r.getColor(
                     R.color.albumset_label_background);
             labelSpec.titleColor = r.getColor(R.color.albumset_label_title);
@@ -80,9 +106,17 @@
 
     public static class AlbumPage {
         private static AlbumPage sInstance;
-
+        public AlbumSlotRenderer.LabelSpec labelSpec;
         public SlotView.Spec slotViewSpec;
         public int placeholderColor;
+        public int paddingTop;
+        public int paddingBottom;
+        public int paddingLeft;
+        public int paddingRight;
+        public int paddingTopLand;
+        public int paddingBottomLand;
+        public int paddingLeftLand;
+        public int paddingRightLand;
 
         public static synchronized AlbumPage get(Context context) {
             if (sInstance == null) {
@@ -97,9 +131,26 @@
             placeholderColor = r.getColor(R.color.album_placeholder);
 
             slotViewSpec = new SlotView.Spec();
-            slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land);
-            slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port);
+            //slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land);
+            //slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port);
+            slotViewSpec.colsLand = r.getInteger(R.integer.album_cols_land);
+            slotViewSpec.colsPort = r.getInteger(R.integer.album_cols_port);
+            slotViewSpec.slotWidth = r.getDimensionPixelSize(R.dimen.slot_width_album);
+            slotViewSpec.slotHeight = r.getDimensionPixelSize(R.dimen.slot_height_album);
             slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.album_slot_gap);
+            slotViewSpec.slotGapLand = r.getDimensionPixelSize(R.dimen.album_slot_gap_land);
+
+            paddingTop = r.getDimensionPixelSize(R.dimen.album_padding_top);
+            paddingBottom = r.getDimensionPixelSize(R.dimen.album_padding_bottom);
+
+            paddingLeft = r.getDimensionPixelSize(R.dimen.album_padding_left);
+            paddingRight = r.getDimensionPixelSize(R.dimen.album_padding_right);
+
+            paddingTopLand = r.getDimensionPixelSize(R.dimen.album_padding_top_land);
+            paddingBottomLand = r.getDimensionPixelSize(R.dimen.album_padding_bottom_land);
+
+            paddingLeftLand = r.getDimensionPixelSize(R.dimen.album_padding_left_land);
+            paddingRightLand = r.getDimensionPixelSize(R.dimen.album_padding_right_land);
         }
     }
 
@@ -123,5 +174,95 @@
             cachePinMargin = r.getDimensionPixelSize(R.dimen.cache_pin_margin);
         }
     }
+
+    public static class AlbumPageList {
+        private static AlbumPageList sInstance;
+
+        public SlotView.Spec slotViewSpec;
+        public AlbumSlotRenderer.LabelSpec labelSpec;
+        public int paddingTop;
+        public int paddingBottom;
+        public int paddingLeft;
+        public int paddingRight;
+        public int placeholderColor;
+
+        public static synchronized AlbumPageList get(Context context) {
+            if (sInstance == null) {
+                sInstance = new AlbumPageList(context);
+            }
+            return sInstance;
+        }
+
+        private AlbumPageList(Context context) {
+            Resources r = context.getResources();
+
+            placeholderColor = r.getColor(R.color.album_placeholder);
+
+            slotViewSpec = new SlotView.Spec();
+            slotViewSpec.slotHeight = r
+                    .getDimensionPixelSize(R.dimen.slot_height_albumlist);
+            slotViewSpec.slotGap = r
+                    .getDimensionPixelSize(R.dimen.albumlist_slot_gap);
+            slotViewSpec.slotGapLand = r
+                    .getDimensionPixelSize(R.dimen.albumlist_slot_gap);
+            paddingTop = r.getDimensionPixelSize(R.dimen.albumlist_padding_top);
+            paddingBottom = r
+                    .getDimensionPixelSize(R.dimen.album_padding_bottom);
+
+            paddingLeft = r.getDimensionPixelSize(R.dimen.albumlist_left_margin);
+            paddingRight = r.getDimensionPixelSize(R.dimen.album_padding_right);
+            labelSpec = new AlbumSlotRenderer.LabelSpec();
+            labelSpec.labelBackgroundHeight = r
+                    .getDimensionPixelSize(R.dimen.albumlist_label_background_height);
+            labelSpec.titleFontSize = r
+                    .getDimensionPixelSize(R.dimen.albumset_title_font_size);
+            labelSpec.leftMargin = r
+                    .getDimensionPixelSize(R.dimen.albumlist_left_margin);
+            labelSpec.titleLeftMargin = r
+                    .getDimensionPixelSize(R.dimen.albumlist_title_margin);
+            labelSpec.iconSize = r
+                    .getDimensionPixelSize(R.dimen.albumlist_thumb_size);
+            labelSpec.backgroundColor = r
+                    .getColor(R.color.albumset_label_background);
+            labelSpec.titleColor = r.getColor(R.color.albumlist_label_title);
+        }
+    }
+
+   public static class TimeLinePage {
+        private static TimeLinePage sInstance;
+
+        public TimeLineSlotView.Spec slotViewSpec;
+        public TimeLineSlotRenderer.LabelSpec labelSpec;
+        public int placeholderColor;
+
+        public static synchronized TimeLinePage get(Context context) {
+            if (sInstance == null) {
+                sInstance = new TimeLinePage(context);
+            }
+            return sInstance;
+        }
+        private TimeLinePage(Context context) {
+            Resources r = context.getResources();
+
+            placeholderColor = r.getColor(R.color.album_placeholder);
+
+            slotViewSpec = new TimeLineSlotView.Spec();
+            slotViewSpec.colsLand = r.getInteger(R.integer.album_cols_land);
+            slotViewSpec.colsPort = r.getInteger(R.integer.album_cols_port);
+            slotViewSpec.slotGapPort = r.getDimensionPixelSize(R.dimen.timeline_port_slot_gap);
+            slotViewSpec.slotGapLand = r.getDimensionPixelSize(R.dimen.timeline_land_slot_gap);
+            slotViewSpec.titleHeight = r.getDimensionPixelSize(R.dimen.timeline_title_height);
+
+            labelSpec = new TimeLineSlotRenderer.LabelSpec();
+
+            labelSpec.timeLineTitleHeight = r.getDimensionPixelSize(
+                    R.dimen.timeline_title_height);
+            labelSpec.timeLineTitleFontSize = r.getDimensionPixelSize(
+                    R.dimen.timeline_title_font_size);
+            labelSpec.timeLineTitleTextColor = r.getColor(R.color.timeline_title_text_color);
+            labelSpec.timeLineNumberTextColor = r.getColor(R.color.timeline_title_number_text_color);
+            labelSpec.timeLineTitleBackgroundColor = r.getColor(R.color.timeline_title_background_color);
+        }
+    }
 }
 
diff --git a/src/com/android/gallery3d/app/ControllerOverlay.java b/src/com/android/gallery3d/app/ControllerOverlay.java
index 078f59e..6f049da 100644
--- a/src/com/android/gallery3d/app/ControllerOverlay.java
+++ b/src/com/android/gallery3d/app/ControllerOverlay.java
@@ -27,6 +27,8 @@
     void onSeekEnd(int time, int trimStartTime, int trimEndTime);
     void onShown();
     void onHidden();
+    // get current video is from RTSP
+    boolean onIsRTSP();
     void onReplay();
   }
 
@@ -53,4 +55,10 @@
 
   void setTimes(int currentTime, int totalTime,
           int trimStartTime, int trimEndTime);
+
+  //set view enabled (play/pause asynchronous processing)
+  void setViewEnabled(boolean isEnabled);
+
+  //view from disable to resume (play/pause asynchronous processing)
+  void setPlayPauseReplayResume();
 }
diff --git a/src/com/android/gallery3d/app/FilterUtils.java b/src/com/android/gallery3d/app/FilterUtils.java
index bc28a9c..af771c1 100644
--- a/src/com/android/gallery3d/app/FilterUtils.java
+++ b/src/com/android/gallery3d/app/FilterUtils.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.app;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.Path;
 
@@ -63,6 +63,7 @@
     public static final int CLUSTER_BY_TAG = 8;
     public static final int CLUSTER_BY_SIZE = 16;
     public static final int CLUSTER_BY_FACE = 32;
+    public static final int CLUSTER_BY_VIDEOS = 64;
 
     public static final int FILTER_IMAGE_ONLY = 1;
     public static final int FILTER_VIDEO_ONLY = 2;
@@ -95,7 +96,7 @@
         setMenuItemApplied(actionBar, CLUSTER_BY_FACE,
                 (ctype & CLUSTER_BY_FACE) != 0, (ccurrent & CLUSTER_BY_FACE) != 0);
 
-        actionBar.setClusterItemVisibility(CLUSTER_BY_ALBUM, !inAlbum || ctype == 0);
+//        actionBar.setClusterItemVisibility(CLUSTER_BY_ALBUM, !inAlbum || ctype == 0);
 
         setMenuItemApplied(actionBar, R.id.action_cluster_album, ctype == 0,
                 ccurrent == 0);
@@ -165,11 +166,11 @@
 
     private static void setMenuItemApplied(
             GalleryActionBar model, int id, boolean applied, boolean updateTitle) {
-        model.setClusterItemEnabled(id, !applied);
+//        model.setClusterItemEnabled(id, !applied);
     }
 
     private static void setMenuItemAppliedEnabled(GalleryActionBar model, int id, boolean applied, boolean enabled, boolean updateTitle) {
-        model.setClusterItemEnabled(id, enabled);
+//        model.setClusterItemEnabled(id, enabled);
     }
 
     // Add a specified filter to the path.
@@ -208,6 +209,8 @@
             case CLUSTER_BY_FACE:
                 kind = "face";
                 break;
+            case CLUSTER_BY_VIDEOS:
+                return "/local/video/-1";
             default: /* CLUSTER_BY_ALBUM */
                 return base;
         }
@@ -215,6 +218,10 @@
         return "/cluster/{" + base + "}/" + kind;
     }
 
+    public static boolean isClusterPath(String path) {
+        return path != null && path.startsWith("/cluster/{");
+    }
+
     // Change the topmost clustering to the specified type.
     public static String switchClusterPath(String base, int clusterType) {
         return newClusterPath(removeOneClusterFromPath(base), clusterType);
diff --git a/src/com/android/gallery3d/app/Gallery.java b/src/com/android/gallery3d/app/Gallery.java
index fd9097d..df3c0f9 100644
--- a/src/com/android/gallery3d/app/Gallery.java
+++ b/src/com/android/gallery3d/app/Gallery.java
@@ -26,7 +26,7 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Intent intent = IntentHelper.getGalleryIntent(Gallery.this);
+        Intent intent = IntentHelper.getGalleryIntent();
         // Since this is being launched from a homescreen shortcut,
         // it's already in a new task. Start Gallery activity and
         // reset the task to its initial state if needed.
diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java
index 588f584..dcea7c4 100644
--- a/src/com/android/gallery3d/app/GalleryActionBar.java
+++ b/src/com/android/gallery3d/app/GalleryActionBar.java
@@ -26,22 +26,24 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
-import android.widget.ShareActionProvider;
 import android.widget.TextView;
+import android.widget.Toolbar;
 import android.widget.TwoLineListItem;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 
 import java.util.ArrayList;
 
-public class GalleryActionBar implements OnNavigationListener {
+public class GalleryActionBar {
     @SuppressWarnings("unused")
     private static final String TAG = "GalleryActionBar";
 
@@ -53,9 +55,9 @@
     private AbstractGalleryActivity mActivity;
     private ActionBar mActionBar;
     private int mCurrentIndex;
-    private ClusterAdapter mAdapter = new ClusterAdapter();
+//    private ClusterAdapter mAdapter = new ClusterAdapter();
 
-    private AlbumModeAdapter mAlbumModeAdapter;
+//    private AlbumModeAdapter mAlbumModeAdapter;
     private OnAlbumModeSelectedListener mAlbumModeListener;
     private int mLastAlbumModeSelected;
     private CharSequence [] mAlbumModes;
@@ -107,7 +109,7 @@
                 R.string.group_by_tags)
     };
 
-    private class ClusterAdapter extends BaseAdapter {
+    /*private class ClusterAdapter extends BaseAdapter {
 
         @Override
         public int getCount() {
@@ -134,9 +136,9 @@
             view.setText(sClusterItems[position].spinnerTitle);
             return convertView;
         }
-    }
+    }*/
 
-    private class AlbumModeAdapter extends BaseAdapter {
+       /*private class AlbumModeAdapter extends BaseAdapter {
         @Override
         public int getCount() {
             return mAlbumModes.length;
@@ -174,7 +176,7 @@
             view.setText((CharSequence) getItem(position));
             return convertView;
         }
-    }
+    }*/
 
     public static String getClusterByTypeString(Context context, int type) {
         for (ActionItem item : sClusterItems) {
@@ -210,104 +212,105 @@
         return mActionBar != null ? mActionBar.getHeight() : 0;
     }
 
-    public void setClusterItemEnabled(int id, boolean enabled) {
-        for (ActionItem item : sClusterItems) {
-            if (item.action == id) {
-                item.enabled = enabled;
-                return;
-            }
-        }
-    }
+//    public void setClusterItemEnabled(int id, boolean enabled) {
+//        for (ActionItem item : sClusterItems) {
+//            if (item.action == id) {
+//                item.enabled = enabled;
+//                return;
+//            }
+//        }
+//    }
 
-    public void setClusterItemVisibility(int id, boolean visible) {
-        for (ActionItem item : sClusterItems) {
-            if (item.action == id) {
-                item.visible = visible;
-                return;
-            }
-        }
-    }
+//    public void setClusterItemVisibility(int id, boolean visible) {
+//        for (ActionItem item : sClusterItems) {
+//            if (item.action == id) {
+//                item.visible = visible;
+//                return;
+//            }
+//        }
+//    }
 
-    public int getClusterTypeAction() {
-        return sClusterItems[mCurrentIndex].action;
-    }
+//    public int getClusterTypeAction() {
+//        return sClusterItems[mCurrentIndex].action;
+//    }
 
-    public void enableClusterMenu(int action, ClusterRunner runner) {
-        if (mActionBar != null) {
-            // Don't set cluster runner until action bar is ready.
-            mClusterRunner = null;
-            mActionBar.setListNavigationCallbacks(mAdapter, this);
-            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
-            setSelectedAction(action);
-            mClusterRunner = runner;
-        }
-    }
+//    public void enableClusterMenu(int action, ClusterRunner runner) {
+//        if (mActionBar != null) {
+//            // Don't set cluster runner until action bar is ready.
+//            mClusterRunner = null;
+////            mActionBar.setListNavigationCallbacks(mAdapter, this);
+//            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+//            setSelectedAction(action);
+//            mClusterRunner = runner;
+//        }
+//    }
 
     // The only use case not to hideMenu in this method is to ensure
     // all elements disappear at the same time when exiting gallery.
     // hideMenu should always be true in all other cases.
-    public void disableClusterMenu(boolean hideMenu) {
-        if (mActionBar != null) {
-            mClusterRunner = null;
-            if (hideMenu) {
-                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
-            }
-        }
-    }
+//    public void disableClusterMenu(boolean hideMenu) {
+//        if (mActionBar != null) {
+//            mClusterRunner = null;
+//            if (hideMenu) {
+//                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+//            }
+//        }
+//    }
 
     public void onConfigurationChanged() {
         if (mActionBar != null && mAlbumModeListener != null) {
-            OnAlbumModeSelectedListener listener = mAlbumModeListener;
-            enableAlbumModeMenu(mLastAlbumModeSelected, listener);
+//            OnAlbumModeSelectedListener listener = mAlbumModeListener;
+//            enableAlbumModeMenu(mLastAlbumModeSelected, listener);
+
         }
     }
 
-    public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) {
-        if (mActionBar != null) {
-            if (mAlbumModeAdapter == null) {
-                // Initialize the album mode options if they haven't been already
-                Resources res = mActivity.getResources();
-                mAlbumModes = new CharSequence[] {
-                        res.getString(R.string.switch_photo_filmstrip),
-                        res.getString(R.string.switch_photo_grid)};
-                mAlbumModeAdapter = new AlbumModeAdapter();
-            }
-            mAlbumModeListener = null;
-            mLastAlbumModeSelected = selected;
-            mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this);
-            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
-            mActionBar.setSelectedNavigationItem(selected);
-            mAlbumModeListener = listener;
-        }
-    }
+//    public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) {
+//        if (mActionBar != null) {
+//            if (mAlbumModeAdapter == null) {
+//                // Initialize the album mode options if they haven't been already
+//                Resources res = mActivity.getResources();
+//                mAlbumModes = new CharSequence[] {
+//                        res.getString(R.string.switch_photo_filmstrip),
+//                        res.getString(R.string.switch_photo_grid)};
+//                mAlbumModeAdapter = new AlbumModeAdapter();
+//            }
+//            mAlbumModeListener = null;
+//            mLastAlbumModeSelected = selected;
+//            mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this);
+//            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
+//            mActionBar.setSelectedNavigationItem(selected);
+//            mAlbumModeListener = listener;
+//        }
+//    }
 
-    public void disableAlbumModeMenu(boolean hideMenu) {
-        if (mActionBar != null) {
-            mAlbumModeListener = null;
-            if (hideMenu) {
-                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
-            }
-        }
-    }
+//    public void disableAlbumModeMenu(boolean hideMenu) {
+//        if (mActionBar != null) {
+//            mAlbumModeListener = null;
+//            if (hideMenu) {
+//                mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+//            }
+//        }
+//    }
 
-    public void showClusterDialog(final ClusterRunner clusterRunner) {
-        createDialogData();
-        final ArrayList<Integer> actions = mActions;
-        new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems(
-                mTitles, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                // Need to lock rendering when operations invoked by system UI (main thread) are
-                // modifying slot data used in GL thread for rendering.
-                mActivity.getGLRoot().lockRenderThread();
-                try {
-                    clusterRunner.doCluster(actions.get(which).intValue());
-                } finally {
-                    mActivity.getGLRoot().unlockRenderThread();
-                }
-            }
-        }).create().show();
-    }
+//    public void showClusterDialog(final ClusterRunner clusterRunner) {
+//        createDialogData();
+//        final ArrayList<Integer> actions = mActions;
+//        new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems(
+//                mTitles, new DialogInterface.OnClickListener() {
+//            @Override
+//            public void onClick(DialogInterface dialog, int which) {
+//                // Need to lock rendering when operations invoked by system UI (main thread) are
+//                // modifying slot data used in GL thread for rendering.
+//                mActivity.getGLRoot().lockRenderThread();
+//                try {
+//                    clusterRunner.doCluster(actions.get(which).intValue());
+//                } finally {
+//                    mActivity.getGLRoot().unlockRenderThread();
+//                }
+//            }
+//        }).create().show();
+//    }
 
     @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
     private void setHomeButtonEnabled(boolean enabled) {
@@ -325,6 +328,17 @@
         mActionBar.setHomeButtonEnabled(displayHomeAsUp);
     }
 
+    public void setDisplayHome(boolean displayHome, boolean showTitle) {
+        if (mActionBar == null) return;
+        int options = 0;
+        if (displayHome) options |= ActionBar.DISPLAY_SHOW_HOME;
+        if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE;
+
+        mActionBar.setDisplayOptions(options,
+                ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
+        mActionBar.setHomeButtonEnabled(displayHome);
+    }
+
     public void setTitle(String title) {
         if (mActionBar != null) mActionBar.setTitle(title);
     }
@@ -355,43 +369,41 @@
         if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener);
     }
 
-    public boolean setSelectedAction(int type) {
-        if (mActionBar == null) return false;
+//    public boolean setSelectedAction(int type) {
+//        if (mActionBar == null) return false;
+//
+//        for (int i = 0, n = sClusterItems.length; i < n; i++) {
+//            ActionItem item = sClusterItems[i];
+//            if (item.action == type) {
+//                mActionBar.setSelectedNavigationItem(i);
+//                mCurrentIndex = i;
+//                return true;
+//            }
+//        }
+//        return false;
+//    }
 
-        for (int i = 0, n = sClusterItems.length; i < n; i++) {
-            ActionItem item = sClusterItems[i];
-            if (item.action == type) {
-                mActionBar.setSelectedNavigationItem(i);
-                mCurrentIndex = i;
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
-        if (itemPosition != mCurrentIndex && mClusterRunner != null
-                || mAlbumModeListener != null) {
-            // Need to lock rendering when operations invoked by system UI (main thread) are
-            // modifying slot data used in GL thread for rendering.
-            mActivity.getGLRoot().lockRenderThread();
-            try {
-                if (mAlbumModeListener != null) {
-                    mAlbumModeListener.onAlbumModeSelected(itemPosition);
-                } else {
-                    mClusterRunner.doCluster(sClusterItems[itemPosition].action);
-                }
-            } finally {
-                mActivity.getGLRoot().unlockRenderThread();
-            }
-        }
-        return false;
-    }
+//    @Override
+//    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+//        if (itemPosition != mCurrentIndex && mClusterRunner != null
+//                || mAlbumModeListener != null) {
+//            // Need to lock rendering when operations invoked by system UI (main thread) are
+//            // modifying slot data used in GL thread for rendering.
+//            mActivity.getGLRoot().lockRenderThread();
+//            try {
+//                if (mAlbumModeListener != null) {
+//                    mAlbumModeListener.onAlbumModeSelected(itemPosition);
+//                } else {
+//                    mClusterRunner.doCluster(sClusterItems[itemPosition].action);
+//                }
+//            } finally {
+//                mActivity.getGLRoot().unlockRenderThread();
+//            }
+//        }
+//        return false;
+//    }
 
     private Menu mActionBarMenu;
-    private ShareActionProvider mSharePanoramaActionProvider;
-    private ShareActionProvider mShareActionProvider;
     private Intent mSharePanoramaIntent;
     private Intent mShareIntent;
 
@@ -401,20 +413,32 @@
 
         MenuItem item = menu.findItem(R.id.action_share_panorama);
         if (item != null) {
-            mSharePanoramaActionProvider = (ShareActionProvider)
-                item.getActionProvider();
-            mSharePanoramaActionProvider
-                .setShareHistoryFileName("panorama_share_history.xml");
-            mSharePanoramaActionProvider.setShareIntent(mSharePanoramaIntent);
+            item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    if (mSharePanoramaIntent != null) {
+                        Intent intent = Intent.createChooser(mSharePanoramaIntent, null);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mContext.startActivity(intent);
+                    }
+                    return true;
+                }
+            });
         }
 
         item = menu.findItem(R.id.action_share);
         if (item != null) {
-            mShareActionProvider = (ShareActionProvider)
-                item.getActionProvider();
-            mShareActionProvider
-                .setShareHistoryFileName("share_history.xml");
-            mShareActionProvider.setShareIntent(mShareIntent);
+            item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    if (mShareIntent != null) {
+                        Intent intent = Intent.createChooser(mShareIntent, null);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mContext.startActivity(intent);
+                    }
+                    return true;
+                }
+            });
         }
     }
 
@@ -422,17 +446,21 @@
         return mActionBarMenu;
     }
 
-    public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent,
-        ShareActionProvider.OnShareTargetSelectedListener onShareListener) {
+    public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent) {
         mSharePanoramaIntent = sharePanoramaIntent;
-        if (mSharePanoramaActionProvider != null) {
-            mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent);
-        }
         mShareIntent = shareIntent;
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setShareIntent(shareIntent);
-            mShareActionProvider.setOnShareTargetSelectedListener(
-                onShareListener);
-        }
     }
+
+    public void setBackGroundTransparent() {
+        mActionBar.setBackgroundDrawable(
+                new ColorDrawable(mContext.getResources().getColor(R.color.photo_page_action_bar)));
+    }
+
+    public void setBackGroundDefault()
+    {
+        mActionBar.setBackgroundDrawable(new ColorDrawable(
+                mContext.getResources().getColor(R.color.primary)));
+    }
+
+
 }
diff --git a/src/com/android/gallery3d/app/GalleryActivity.java b/src/com/android/gallery3d/app/GalleryActivity.java
old mode 100644
new mode 100755
index bb2a6b8..5275df8
--- a/src/com/android/gallery3d/app/GalleryActivity.java
+++ b/src/com/android/gallery3d/app/GalleryActivity.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
  * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,19 +21,38 @@
 
 import android.app.Dialog;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
+import android.content.UriMatcher;
+import android.content.pm.PackageManager;
+import android.graphics.Color;
 import android.net.Uri;
 import android.os.Bundle;
+import androidx.drawerlayout.widget.DrawerLayout;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
 import android.view.InputDevice;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.Window;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.RelativeLayout.LayoutParams;
+import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.Toolbar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
@@ -39,6 +61,10 @@
 import com.android.gallery3d.picasasource.PicasaSource;
 import com.android.gallery3d.util.GalleryUtils;
 
+import com.google.android.material.bottomnavigation.BottomNavigationView;
+
+import java.util.Locale;
+
 public final class GalleryActivity extends AbstractGalleryActivity implements OnCancelListener {
     public static final String EXTRA_SLIDESHOW = "slideshow";
     public static final String EXTRA_DREAM = "dream";
@@ -50,28 +76,172 @@
     public static final String KEY_TYPE_BITS = "type-bits";
     public static final String KEY_MEDIA_TYPES = "mediaTypes";
     public static final String KEY_DISMISS_KEYGUARD = "dismiss-keyguard";
+    public static final String KEY_FROM_SNAPCAM = "from-snapcam";
+    public static final String KEY_TOTAL_NUMBER = "total-number";
+    public static final String QSST = "QSST";
+
+    private static final int ALL_DOWNLOADS = 1;
+    private static final int ALL_DOWNLOADS_ID = 2;
+    private static final UriMatcher sURIMatcher =
+            new UriMatcher(UriMatcher.NO_MATCH);
+    public static final String PERMISSION_ACCESS_ALL =
+            "android.permission.ACCESS_ALL_DOWNLOADS";
+    static {
+        sURIMatcher.addURI("downloads", "all_downloads", ALL_DOWNLOADS);
+        sURIMatcher.addURI("downloads", "all_downloads/#", ALL_DOWNLOADS_ID);
+    }
 
     private static final String TAG = "GalleryActivity";
     private Dialog mVersionCheckDialog;
+    private ListView mDrawerListView;
+    private DrawerLayout mDrawerLayout;
+    public static boolean mIsparentActivityFInishing;
+    public Toolbar mToolbar;
+
+    private BottomNavigationView mBottomNavigation;
+    private RelativeLayout mGLParentLayout;
+    private RelativeLayout.LayoutParams params;
+
+    /** DrawerLayout is not supported in some entrances.
+     * such as Intent.ACTION_VIEW, Intent.ACTION_GET_CONTENT, Intent.PICK. */
+    private boolean mDrawerLayoutSupported = true;
+
+    private static final int PERMISSION_REQUEST_STORAGE = 1;
+    private Bundle mSavedInstanceState;
+    private boolean mIsViewInited = false;
+
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR);
-        requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
 
         if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) {
             getWindow().addFlags(
                     WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
         }
 
-        setContentView(R.layout.main);
+        setContentView(R.layout.gallery_main);
+        initView();
+        mIsViewInited = true;
 
-        if (savedInstanceState != null) {
-            getStateManager().restoreFromState(savedInstanceState);
+        mSavedInstanceState = savedInstanceState;
+        if (isPermissionGranted()) {
+            init();
+        }
+    }
+
+    private void init() {
+        if (mSavedInstanceState != null) {
+            getStateManager().restoreFromState(mSavedInstanceState);
         } else {
             initializeByIntent();
         }
+        mSavedInstanceState = null;
+    }
+
+    @Override
+    protected void onGetPermissionsSuccess() {
+        if (mIsViewInited) {
+            init();
+        }
+    }
+
+    @Override
+    protected void onGetPermissionsFailure() {
+        finish();
+    }
+
+    private static class ActionItem {
+        public int action;
+        public int title;
+        public int icon;
+
+        public ActionItem(int action, int title, int icon) {
+            this.action = action;
+            this.title = title;
+            this.icon = icon;
+        }
+    }
+
+    private static final ActionItem[] sActionItems = new ActionItem[] {
+            new ActionItem(FilterUtils.CLUSTER_BY_TIME,
+                    R.string.timeline_title, R.drawable.timeline),
+            new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, R.string.albums_title,
+                    R.drawable.albums),
+            new ActionItem(FilterUtils.CLUSTER_BY_VIDEOS,
+                    R.string.videos_title, R.drawable.videos) };
+
+    public void initView() {
+        mToolbar = (Toolbar) findViewById(R.id.toolbar);
+        setActionBar(mToolbar);
+        setToolbar(mToolbar);
+
+        mGLParentLayout = (RelativeLayout) findViewById(R.id.gl_parent_layout);
+        params = (RelativeLayout.LayoutParams) mGLParentLayout.getLayoutParams();
+
+        mBottomNavigation = (BottomNavigationView) findViewById(R.id.bottom_navigation);
+        mBottomNavigation.setOnNavigationItemSelectedListener(
+                new BottomNavigationView.OnNavigationItemSelectedListener() {
+            @Override
+            public boolean onNavigationItemSelected(MenuItem item) {
+                getGLRoot().lockRenderThread();
+                switch (item.getItemId()) {
+                    case R.id.action_timeline:
+                        showScreen(0);
+                        break;
+                    case R.id.action_album:
+                        showScreen(1);
+                        break;
+                    case R.id.action_videos:
+                        showScreen(2);
+                        break;
+                }
+                getGLRoot().unlockRenderThread();
+                return true;
+            }
+        });
+    }
+
+    public void toggleNavBar(boolean show) {
+        if (show) {
+            mBottomNavigation.setVisibility(View.VISIBLE);
+        } else {
+            mBottomNavigation.setVisibility(View.GONE);
+        }
+    }
+
+    public void showScreen(int position) {
+        if (position > 2) {
+            position = 1;
+        }
+        // Bundle data = new Bundle();
+        // int clusterType;
+        // String newPath;
+        String basePath = getDataManager().getTopSetPath(
+                DataManager.INCLUDE_ALL);
+        switch (position) {
+
+        case 0:
+            startTimelinePage(); //Timeline view
+            break;
+        case 1:
+            startAlbumPage(); // Albums View
+            break;
+        case 2:
+            startVideoPage(); // Videos view
+            break;
+        default:
+            break;
+        }
+    }
+
+    public static int getActionTitle(Context context, int type) {
+        for (ActionItem item : sActionItems) {
+            if (item.action == type) {
+                return item.title;
+            }
+        }
+        return -1;
     }
 
     private void initializeByIntent() {
@@ -79,8 +249,11 @@
         String action = intent.getAction();
 
         if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) {
+            mDrawerLayoutSupported = false;
             startGetContent(intent);
+            toggleNavBar(false);
         } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) {
+            mDrawerLayoutSupported = false;
             // We do NOT really support the PICK intent. Handle it as
             // the GET_CONTENT. However, we need to translate the type
             // in the intent here.
@@ -91,20 +264,96 @@
                 if (type.endsWith("/video")) intent.setType("video/*");
             }
             startGetContent(intent);
+            toggleNavBar(false);
         } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action)
                 || ACTION_REVIEW.equalsIgnoreCase(action)){
+            mDrawerLayoutSupported = false;
+            Uri uri = intent.getData();
+            if (uri != null) {
+                int flag = intent.getFlags();
+                int match = sURIMatcher.match(uri);
+                if ((match == ALL_DOWNLOADS || match == ALL_DOWNLOADS_ID) &&
+                       (flag & Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0) {
+                    if (checkCallingOrSelfPermission(
+                            PERMISSION_ACCESS_ALL) != PackageManager.PERMISSION_GRANTED) {
+                        Log.w(TAG, "no permission to view: " + uri);
+                        return;
+                    }
+                }
+            } else {
+                Log.w(TAG, "uri get from intent is null");
+            }
             startViewAction(intent);
+            toggleNavBar(false);
         } else {
-            startDefaultPage();
+            mDrawerLayoutSupported = true;
+            startTimelinePage();
+            mToolbar.setTitle(R.string.albums_title);
+        }
+        toggleNavBar(mDrawerLayoutSupported);
+    }
+
+    public void startAlbumPage() {
+        PicasaSource.showSignInReminder(this);
+        Bundle data = new Bundle();
+        int clusterType = FilterUtils.CLUSTER_BY_ALBUM;
+        data.putString(AlbumSetPage.KEY_MEDIA_PATH, getDataManager()
+                .getTopSetPath(DataManager.INCLUDE_ALL));
+        if (getStateManager().getStateCount() == 0)
+            getStateManager().startState(AlbumSetPage.class, data);
+        else {
+            ActivityState state = getStateManager().getTopState();
+            String oldClass = state.getClass().getSimpleName();
+            String newClass = AlbumSetPage.class.getSimpleName();
+            if (!oldClass.equals(newClass)) {
+             getStateManager().switchState(getStateManager().getTopState(),
+                    AlbumSetPage.class, data);
+            }
+        }
+        mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this);
+        if (mVersionCheckDialog != null) {
+            mVersionCheckDialog.setOnCancelListener(this);
         }
     }
 
-    public void startDefaultPage() {
-        PicasaSource.showSignInReminder(this);
+   private void startTimelinePage() {
+        String newBPath = getDataManager().getTopSetPath(DataManager.INCLUDE_ALL);
+        String newPath = FilterUtils.switchClusterPath(newBPath, FilterUtils.CLUSTER_BY_TIME);
         Bundle data = new Bundle();
-        data.putString(AlbumSetPage.KEY_MEDIA_PATH,
-                getDataManager().getTopSetPath(DataManager.INCLUDE_ALL));
-        getStateManager().startState(AlbumSetPage.class, data);
+        data.putString(TimeLinePage.KEY_MEDIA_PATH, newPath);
+        if (getStateManager().getStateCount() == 0)
+            getStateManager().startState(TimeLinePage.class, data);
+        else {
+            ActivityState state = getStateManager().getTopState();
+            String oldClass = state.getClass().getSimpleName();
+            String newClass = TimeLinePage.class.getSimpleName();
+            if (!oldClass.equals(newClass)) {
+            getStateManager().switchState(getStateManager().getTopState(),
+                    TimeLinePage.class, data);
+            }
+        }
+        mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this);
+        if (mVersionCheckDialog != null) {
+            mVersionCheckDialog.setOnCancelListener(this);
+        }
+    }
+
+   public void startVideoPage() {
+        PicasaSource.showSignInReminder(this);
+        String basePath = getDataManager().getTopSetPath(
+                DataManager.INCLUDE_ALL);
+        Bundle data = new Bundle();
+        int clusterType = FilterUtils.CLUSTER_BY_VIDEOS;
+        String newPath = FilterUtils.switchClusterPath(basePath, clusterType);
+        data.putString(AlbumPage.KEY_MEDIA_PATH, newPath);
+        data.putBoolean(AlbumPage.KEY_IS_VIDEOS_SCREEN, true);
+        ActivityState state = getStateManager().getTopState();
+        String oldClass = state.getClass().getSimpleName();
+        String newClass = AlbumPage.class.getSimpleName();
+        if (!oldClass.equals(newClass)) {
+        getStateManager().switchState(getStateManager().getTopState(),
+                AlbumPage.class, data);
+        }
         mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this);
         if (mVersionCheckDialog != null) {
             mVersionCheckDialog.setOnCancelListener(this);
@@ -199,14 +448,23 @@
                         getStateManager().startState(AlbumSetPage.class, data);
                     }
                 } else {
-                    startDefaultPage();
+                    startTimelinePage();
                 }
             } else {
                 Path itemPath = dm.findPathByUri(uri, contentType);
                 Path albumPath = dm.getDefaultSetOf(itemPath);
 
                 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, itemPath.toString());
-                data.putBoolean(PhotoPage.KEY_READONLY, true);
+                if (!intent.getBooleanExtra(KEY_FROM_SNAPCAM, false)) {
+                    data.putBoolean(PhotoPage.KEY_READONLY, true);
+                } else {
+                    int hintIndex = 0;
+                    if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                        hintIndex = intent.getIntExtra(KEY_TOTAL_NUMBER, 1) - 1;
+                    }
+                    data.putInt(PhotoPage.KEY_INDEX_HINT, hintIndex);
+                }
 
                 // TODO: Make the parameter "SingleItemOnly" public so other
                 //       activities can reference it.
@@ -214,15 +472,11 @@
                         || intent.getBooleanExtra("SingleItemOnly", false);
                 if (!singleItemOnly) {
                     data.putString(PhotoPage.KEY_MEDIA_SET_PATH, albumPath.toString());
-                    // when FLAG_ACTIVITY_NEW_TASK is set, (e.g. when intent is fired
-                    // from notification), back button should behave the same as up button
-                    // rather than taking users back to the home screen
-                    if (intent.getBooleanExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, false)
-                            || ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)) {
-                        data.putBoolean(PhotoPage.KEY_TREAT_BACK_AS_UP, true);
-                    }
                 }
-
+                data.putBoolean("SingleItemOnly", singleItemOnly);
+                // set the cover View to black
+                View cover = findViewById(R.id.gl_root_cover);
+                cover.setBackgroundColor(Color.BLACK);
                 getStateManager().startState(SinglePhotoPage.class, data);
             }
         }
@@ -230,7 +484,6 @@
 
     @Override
     protected void onResume() {
-        Utils.assertTrue(getStateManager().getStateCount() > 0);
         super.onResume();
         if (mVersionCheckDialog != null) {
             mVersionCheckDialog.show();
@@ -246,6 +499,11 @@
     }
 
     @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    @Override
     public void onCancel(DialogInterface dialog) {
         if (dialog == mVersionCheckDialog) {
             mVersionCheckDialog = null;
diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java
index c6e7a0b..9c5f232 100644
--- a/src/com/android/gallery3d/app/GalleryAppImpl.java
+++ b/src/com/android/gallery3d/app/GalleryAppImpl.java
@@ -36,6 +36,7 @@
 
     private static final String DOWNLOAD_FOLDER = "download";
     private static final long DOWNLOAD_CAPACITY = 64 * 1024 * 1024; // 64M
+    private static GalleryAppImpl sGalleryAppImpl;
 
     private ImageCacheService mImageCacheService;
     private Object mLock = new Object();
@@ -51,6 +52,7 @@
         WidgetUtils.initialize(this);
         PicasaSource.initialize(this);
         UsageStatistics.initialize(this);
+        sGalleryAppImpl = this;
     }
 
     @Override
@@ -58,6 +60,10 @@
         return this;
     }
 
+    public static Context getContext() {
+        return sGalleryAppImpl;
+    }
+
     @Override
     public synchronized DataManager getDataManager() {
         if (mDataManager == null) {
diff --git a/src/com/android/gallery3d/app/GestureController.java b/src/com/android/gallery3d/app/GestureController.java
new file mode 100644
index 0000000..22deb67
--- /dev/null
+++ b/src/com/android/gallery3d/app/GestureController.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+public class GestureController {
+    private static final int GESTURE_THRESHOLD = 20;
+    private GestureDetector mGestureDetector;
+    private GestureControlListener mGestureControlListener;
+
+    private Rect mFullRect = new Rect();
+    private Rect mBrightnessRect = new Rect();
+    private Rect mVolumeRect = new Rect();
+    private Type mType = Type.NONE;
+
+    private MotionEvent mStartEvent;
+
+    public GestureController(Context context, GestureControlListener gestureControlListener) {
+        mGestureControlListener = gestureControlListener;
+        mGestureDetector =
+                new GestureDetector(context, new GestureListener(gestureControlListener));
+    }
+
+    public interface GestureControlListener {
+        void onGestureDone(boolean notStart);
+        /**
+         * change current windows brightness by add adjustPercent.
+         *
+         * @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
+         *            decrease if adjustPercent < 0;
+         */
+        void adjustBrightness(double adjustPercent);
+
+        /**
+         * change volume level by add adjustPercent.
+         *
+         * @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
+         *            decrease if adjustPercent < 0;
+         */
+        void adjustVolumeLevel(double adjustPercent);
+
+        /**
+         * change video position by add adjustPercent.
+         *
+         * @param adjustPercent: -1.0f ~ 1.0f, increase if adjustPercent > 0,
+         *            decrease if adjustPercent < 0;
+         * @param forwardDirection: true if direction is forward.
+         */
+        void adjustVideoPosition(double adjustPercent, boolean forwardDirection);
+    }
+
+    private enum Type {
+        NONE,
+        BRIGHTNESS,
+        VOLUME,
+        SEEK,
+    }
+
+    public void setRect(Rect rect) {
+        this.setRect(rect.left, rect.top, rect.right, rect.bottom);
+    }
+
+    public void setRect(int l, int t, int r, int b) {
+        mFullRect.left = l;
+        mFullRect.top = t;
+        mFullRect.right = r;
+        mFullRect.bottom = b;
+
+        mBrightnessRect.left = l;
+        mBrightnessRect.top = t;
+        mBrightnessRect.right = r / 2;
+        mBrightnessRect.bottom = b;
+
+        mVolumeRect.left = l / 2;
+        mVolumeRect.top = t;
+        mVolumeRect.right = r;
+        mVolumeRect.bottom = b;
+    }
+
+    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
+        private GestureControlListener mGestureControlListener;
+
+        public GestureListener(GestureControlListener controlListener) {
+            mGestureControlListener = controlListener;
+        }
+
+        @Override
+        public boolean onScroll(MotionEvent start, MotionEvent end,
+                                float distanceX, float distanceY) {
+            if (mGestureControlListener == null) {
+                return super.onScroll(start, end, distanceX, distanceY);
+            }
+            // function depends on start position. (volume or brightness or play position.)
+            double yDistance = end.getY() - start.getY();
+            double xDistance = end.getX() - start.getX();
+
+            if (mType == Type.BRIGHTNESS) {
+                // use half of BrightnessRect's height to calc percent.
+                if (mBrightnessRect.height() != 0) {
+                    double percent = yDistance / (mBrightnessRect.height() / 2.0f) * -1.0f;
+                    mGestureControlListener.adjustBrightness(percent);
+                }
+            } else if (mType == Type.VOLUME) {
+                // use half of VolumeRect's height to calc percent.
+                if (mVolumeRect.height() != 0) {
+                    double percent = yDistance / (mVolumeRect.height() / 2.0f) * -1.0f;
+                    mGestureControlListener.adjustVolumeLevel(percent);
+                }
+            } else if (mType == Type.SEEK) {
+                if (mFullRect.width() != 0) {
+                    double percent = xDistance / mFullRect.width();
+                    mGestureControlListener.adjustVideoPosition(percent, distanceX < 0);
+                }
+            }
+            return true;
+        }
+    }
+
+    private boolean isEventValid(MotionEvent event) {
+        // this gesture just worked on single pointer.
+        return (mGestureDetector != null && event.getPointerCount() == 1);
+    }
+
+    public boolean onTouchEvent(MotionEvent event) {
+        if (!isEventValid(event)) {
+            return false;
+        }
+        // decide which process is needed.
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mStartEvent = MotionEvent.obtain(event);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mType == Type.NONE && mStartEvent != null) {
+                    mType = calcControllerType(mStartEvent, event);
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mGestureControlListener != null) {
+                    if (mType == Type.NONE) {
+                        mGestureControlListener.onGestureDone(true);
+                    } else {
+                        mGestureControlListener.onGestureDone(false);
+                    }
+                }
+                mType = Type.NONE;
+                mStartEvent = null;
+                break;
+            default:
+                break;
+        }
+
+        return mGestureDetector.onTouchEvent(event);
+    }
+
+    private Type calcControllerType(MotionEvent startEvent, MotionEvent currentEvent) {
+        float startX = startEvent.getX();
+        float startY = startEvent.getY();
+        float currentX = currentEvent.getX();
+        float currentY = currentEvent.getY();
+        if (Math.abs(currentX - startX) >= GESTURE_THRESHOLD) {
+            return Type.SEEK;
+        } else if (Math.abs(currentY - startY) >= GESTURE_THRESHOLD) {
+            if (mBrightnessRect.contains((int) startX, (int) startY)) {
+                return Type.BRIGHTNESS;
+            } else if (mVolumeRect.contains((int) startX, (int) startY)) {
+                return Type.VOLUME;
+            }
+        }
+        return Type.NONE;
+    }
+}
diff --git a/src/com/android/gallery3d/app/GestureControllerOverlay.java b/src/com/android/gallery3d/app/GestureControllerOverlay.java
new file mode 100755
index 0000000..9060490
--- /dev/null
+++ b/src/com/android/gallery3d/app/GestureControllerOverlay.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.media.AudioManager;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import android.widget.TextView;
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.util.GalleryUtils;
+
+public class GestureControllerOverlay extends FrameLayout implements
+        ControllerOverlay, GestureController.GestureControlListener {
+    private GestureController mGestureController;
+
+    private static final int MAX_VIDEO_STEP_TIME = 60 * 1000;
+    private static final int MAX_BRIGHTNESS = 100;
+
+    private float mStartBrightness = -1.0f;
+    private double mStartVolumePercent = -1.0f;
+    private int mStartVideoTime = -1;
+
+    private TextView mCurrentIndicator;
+    private Drawable mBrightnessDrawable;
+    private Drawable mVolumeDrawable;
+    private Drawable mRewindDrawable;
+    private Drawable mForwardDrawable;
+
+    private final int mIndicatorHeight;
+    private final int mIndicatorWidth;
+    private final int mIndicatorIconSize;
+    private final int mIndicatorTextSize;
+
+    private Listener mListener;
+    private TimeBar mTimeBar;
+
+    private CommonControllerOverlay mControllerOverlay;
+
+    public GestureControllerOverlay(Context context) {
+        super(context);
+        Resources res = getResources();
+        mIndicatorHeight = res.getDimensionPixelSize(R.dimen.controller_indicator_height);
+        mIndicatorWidth = res.getDimensionPixelSize(R.dimen.controller_indicator_width);
+        mIndicatorIconSize = res.getDimensionPixelSize(R.dimen.controller_indicator_icon_size);
+        mIndicatorTextSize = res.getDimensionPixelSize(R.dimen.controller_indicator_text_size);
+        init(context);
+    }
+
+    public GestureControllerOverlay(Context context,
+                                    MovieControllerOverlay movieControllerOverlay) {
+        this(context);
+        mControllerOverlay = movieControllerOverlay;
+        if (movieControllerOverlay instanceof MovieControllerOverlayNew) {
+            mTimeBar = ((MovieControllerOverlayNew) movieControllerOverlay).getTimeBar();
+        }
+    }
+
+    private void init(Context context) {
+        mGestureController = new GestureController(context, this);
+
+        mBrightnessDrawable = getResources().getDrawable(R.drawable.ic_controller_brightness, null);
+        if (mBrightnessDrawable != null) {
+            mBrightnessDrawable.setBounds(0, 0, mIndicatorIconSize, mIndicatorIconSize);
+        }
+
+        mVolumeDrawable = getResources().getDrawable(R.drawable.ic_controller_volume, null);
+        if (mVolumeDrawable != null) {
+            mVolumeDrawable.setBounds(0, 0, mIndicatorIconSize, mIndicatorIconSize);
+        }
+
+        mRewindDrawable = getResources().getDrawable(R.drawable.ic_menu_rewind, null);
+        if (mRewindDrawable != null) {
+            mRewindDrawable.setBounds(0, 0, mIndicatorIconSize, mIndicatorIconSize);
+        }
+
+        mForwardDrawable = getResources().getDrawable(R.drawable.ic_menu_forward, null);
+        if (mForwardDrawable != null) {
+            mForwardDrawable.setBounds(0, 0, mIndicatorIconSize, mIndicatorIconSize);
+        }
+
+        LayoutParams matchParent =
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        View background = new View(context);
+        background.setBackgroundColor(Color.TRANSPARENT);
+        addView(background, matchParent);
+
+        LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, mIndicatorHeight);
+        int paddingH = getResources().getDimensionPixelSize(R.dimen.controller_indicator_padding_h);
+        int paddingV = getResources().getDimensionPixelSize(R.dimen.controller_indicator_padding_v);
+        mCurrentIndicator = new TextView(context);
+        mCurrentIndicator.setBackgroundResource(R.drawable.bg_controller_indicator);
+        mCurrentIndicator.setPadding(paddingH, paddingV, paddingH, paddingV);
+        mCurrentIndicator.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
+        mCurrentIndicator.setTextSize(TypedValue.COMPLEX_UNIT_PX, mIndicatorTextSize);
+        mCurrentIndicator.setTextColor(Color.WHITE);
+        mCurrentIndicator.setMinWidth(mIndicatorWidth);
+        addView(mCurrentIndicator, layoutParams);
+        mCurrentIndicator.setVisibility(INVISIBLE);
+    }
+
+    private void showIndicator() {
+        if (mCurrentIndicator != null) {
+            mCurrentIndicator.setAlpha(1.0f);
+            mCurrentIndicator.setVisibility(VISIBLE);
+        }
+    }
+
+    private void hideIndicator() {
+        if (mCurrentIndicator != null) {
+            mCurrentIndicator.setText(null);
+            mCurrentIndicator.setVisibility(INVISIBLE);
+        }
+    }
+
+    public void doOnPause() {
+        hideIndicator();
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mGestureController != null) {
+            mGestureController.onTouchEvent(event);
+        }
+        return true;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        measureChildren(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (changed && mGestureController != null) {
+            mGestureController.setRect(left, top, right, bottom);
+        }
+
+        int h = bottom - top;
+        int w = right - left;
+
+        if (mCurrentIndicator != null) {
+            layoutCenteredView(mCurrentIndicator, 0, 0, w, h);
+        }
+    }
+
+    protected void layoutCenteredView(View view, int l, int t, int r, int b) {
+        int cw = view.getMeasuredWidth();
+        int ch = view.getMeasuredHeight();
+        int cl = (r - l - cw) / 2;
+        int ct = (b - t - ch) / 2;
+        view.layout(cl, ct, cl + cw, ct + ch);
+    }
+
+    @Override
+    public void onGestureDone(boolean notStart) {
+        mStartBrightness = -1.0f;
+        mStartVolumePercent = -1.0f;
+        mStartVideoTime = -1;
+        hideIndicator();
+
+        if (notStart) {
+            if (mControllerOverlay != null) {
+                if (mControllerOverlay.isShown())
+                    mControllerOverlay.hide();
+                else
+                    mControllerOverlay.show();
+            }
+
+        }
+    }
+
+    @Override
+    public void adjustBrightness(double adjustPercent) {
+        if (adjustPercent < -1.0f) {
+            adjustPercent = -1.0f;
+        } else if (adjustPercent > 1.0f) {
+            adjustPercent = 1.0f;
+        }
+
+        WindowManager.LayoutParams lp = ((MovieActivity) getContext()).getWindow().getAttributes();
+        if (mStartBrightness < 0) {
+            mStartBrightness = lp.screenBrightness;
+        }
+        float targetBrightness = (float) (mStartBrightness + adjustPercent * 1.0f);
+        if (targetBrightness <= 0.0f) {
+            targetBrightness = 0.004f;
+        } else if (targetBrightness >= 1.0f) {
+            targetBrightness = 1.0f;
+        }
+        lp.screenBrightness = targetBrightness;
+        ((MovieActivity) getContext()).getWindow().setAttributes(lp);
+
+        if (mCurrentIndicator != null) {
+            mCurrentIndicator.setCompoundDrawables(null, mBrightnessDrawable, null, null);
+            mCurrentIndicator.setText((int) (targetBrightness * MAX_BRIGHTNESS) + "%");
+        }
+        showIndicator();
+    }
+
+    @Override
+    public void adjustVolumeLevel(double adjustPercent) {
+        if (adjustPercent < -1.0f) {
+            adjustPercent = -1.0f;
+        } else if (adjustPercent > 1.0f) {
+            adjustPercent = 1.0f;
+        }
+
+        AudioManager audioManager = (AudioManager) getContext()
+                .getSystemService(Context.AUDIO_SERVICE);
+        final int STREAM = AudioManager.STREAM_MUSIC;
+        int maxVolume = audioManager.getStreamMaxVolume(STREAM);
+
+        if (maxVolume == 0) return;
+
+        if (mStartVolumePercent < 0) {
+            int curVolume = audioManager.getStreamVolume(STREAM);
+            mStartVolumePercent = curVolume * 1.0f / maxVolume;
+        }
+        double targetPercent = mStartVolumePercent + adjustPercent;
+        if (targetPercent > 1.0f) {
+            targetPercent = 1.0f;
+        } else if (targetPercent < 0) {
+            targetPercent = 0;
+        }
+
+        int index = (int) (maxVolume * targetPercent);
+        if (index > maxVolume) {
+            index = maxVolume;
+        } else if (index < 0) {
+            index = 0;
+        }
+        audioManager.setStreamVolume(STREAM, index, 0);
+
+        if (mCurrentIndicator != null) {
+            mCurrentIndicator.setCompoundDrawables(null, mVolumeDrawable, null, null);
+            mCurrentIndicator.setText(index * 100 / maxVolume + "%");
+        }
+        showIndicator();
+    }
+
+    @Override
+    public void adjustVideoPosition(double adjustPercent, boolean forwardDirection) {
+        if (mTimeBar == null || !(mTimeBar instanceof TimeBarNew)) {
+            return;
+        }
+
+        if (!((TimeBarNew) mTimeBar).seekable() || !mTimeBar.getScrubbing()
+                || !mTimeBar.isClickable()) {
+            return;
+        }
+
+        if (adjustPercent < -1.0f) {
+            adjustPercent = -1.0f;
+        } else if (adjustPercent > 1.0f) {
+            adjustPercent = 1.0f;
+        }
+
+        int totalTime = ((TimeBarNew) mTimeBar).getTotalTime();
+
+        if (mStartVideoTime < 0) {
+            mStartVideoTime = ((TimeBarNew) mTimeBar).getCurrentTime();
+        }
+
+        int targetTime = mStartVideoTime + (int) (MAX_VIDEO_STEP_TIME * adjustPercent);
+        if (targetTime > totalTime) {
+            targetTime = totalTime;
+        }
+        if (targetTime < 0) {
+            targetTime = 0;
+        }
+
+        String targetTimeString = GalleryUtils.formatDuration(getContext(), targetTime / 1000);
+
+        if (forwardDirection) {
+            if (mCurrentIndicator != null) {
+                mCurrentIndicator.setCompoundDrawables(null, mForwardDrawable, null, null);
+                mCurrentIndicator.setText(targetTimeString);
+            }
+        } else {
+            if (mCurrentIndicator != null) {
+                mCurrentIndicator.setCompoundDrawables(null, mRewindDrawable, null, null);
+                mCurrentIndicator.setText(targetTimeString);
+            }
+        }
+
+        if (mListener != null) {
+            mListener.onSeekEnd(targetTime, 0, 0);
+        }
+        if (mTimeBar != null) {
+            mTimeBar.setTime(targetTime, totalTime, 0, 0);
+        }
+
+        showIndicator();
+    }
+
+    @Override
+    public void setListener(Listener listener) {
+        this.mListener = listener;
+    }
+
+    @Override
+    public void setCanReplay(boolean canReplay) {
+
+    }
+
+    @Override
+    public View getView() {
+        return this;
+    }
+
+    @Override
+    public void show() {
+
+    }
+
+    @Override
+    public void showPlaying() {
+
+    }
+
+    @Override
+    public void showPaused() {
+
+    }
+
+    @Override
+    public void showEnded() {
+
+    }
+
+    @Override
+    public void showLoading() {
+
+    }
+
+    @Override
+    public void showErrorMessage(String message) {
+
+    }
+
+    @Override
+    public void setTimes(int currentTime, int totalTime, int trimStartTime, int trimEndTime) {
+
+    }
+
+    @Override
+    public void setViewEnabled(boolean isEnabled) {
+
+    }
+
+    @Override
+    public void setPlayPauseReplayResume() {
+
+    }
+}
diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java
index 4f5c358..c945199 100644
--- a/src/com/android/gallery3d/app/ManageCachePage.java
+++ b/src/com/android/gallery3d/app/ManageCachePage.java
@@ -30,7 +30,7 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaSet;
diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java
index 1547f6f..fa4a0f9 100644
--- a/src/com/android/gallery3d/app/MovieActivity.java
+++ b/src/com/android/gallery3d/app/MovieActivity.java
@@ -18,18 +18,28 @@
 
 import android.annotation.TargetApi;
 import android.app.ActionBar;
-import android.app.Activity;
+import android.app.ActionBar.OnMenuVisibilityListener;
+import android.app.KeyguardManager;
 import android.content.AsyncQueryHandler;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
 import android.content.pm.ActivityInfo;
 import android.database.Cursor;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.drawable.BitmapDrawable;
-import android.media.AudioManager;
+import android.graphics.drawable.ColorDrawable;
+import android.media.MediaPlayer;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.PowerManager;
 import android.provider.MediaStore;
 import android.provider.OpenableColumns;
 import android.view.KeyEvent;
@@ -38,11 +48,17 @@
 import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
-import android.widget.ShareActionProvider;
+import android.widget.ImageView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
+import org.codeaurora.gallery3d.ext.IActivityHooker;
+import org.codeaurora.gallery3d.ext.IMovieItem;
+import org.codeaurora.gallery3d.ext.MovieItem;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+import org.codeaurora.gallery3d.video.ExtensionHelper;
+import org.codeaurora.gallery3d.video.MovieTitleHelper;
 
 /**
  * This activity plays a video from a specified URI.
@@ -51,16 +67,34 @@
  * to set the action bar logo so the playback process looks more seamlessly integrated with
  * the original activity.
  */
-public class MovieActivity extends Activity {
+public class MovieActivity extends AbstractPermissionActivity {
     @SuppressWarnings("unused")
-    private static final String TAG = "MovieActivity";
-    public static final String KEY_LOGO_BITMAP = "logo-bitmap";
-    public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
+    private static final String  TAG = "MovieActivity";
+    private static final boolean LOG = false;
+    public  static final String  KEY_LOGO_BITMAP = "logo-bitmap";
+    public  static final String  KEY_TREAT_UP_AS_BACK = "treat-up-as-back";
+    private static final String  VIDEO_SDP_MIME_TYPE = "application/sdp";
+    private static final String  VIDEO_SDP_TITLE = "rtsp://";
+    private static final String  VIDEO_FILE_SCHEMA = "file";
+    private static final String  VIDEO_MIME_TYPE = "video/*";
+    private static final String  SHARE_HISTORY_FILE = "video_share_history_file";
 
     private MoviePlayer mPlayer;
-    private boolean mFinishOnCompletion;
-    private Uri mUri;
-    private boolean mTreatUpAsBack;
+    private boolean     mFinishOnCompletion;
+    private Uri         mUri;
+    private ImageView   mLiveImg;
+    private boolean     mUserPresentReceived = false;
+
+    private IMovieItem          mMovieItem;
+    private IActivityHooker     mMovieHooker;
+    private KeyguardManager     mKeyguardManager;
+    private Bundle mSavedInstanceState;
+
+    private boolean mResumed        = false;
+    private boolean mControlResumed = false;
+
+    private Intent mShareIntent;
+    private PowerManager.WakeLock mWakeLock = null;
 
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private void setSystemUiVisibility(View rootView) {
@@ -83,17 +117,40 @@
 
         setSystemUiVisibility(rootView);
 
+        mLiveImg = (ImageView) findViewById(R.id.img_live);
+
         Intent intent = getIntent();
+
         initializeActionBar(intent);
         mFinishOnCompletion = intent.getBooleanExtra(
                 MediaStore.EXTRA_FINISH_ON_COMPLETION, true);
-        mTreatUpAsBack = intent.getBooleanExtra(KEY_TREAT_UP_AS_BACK, false);
-        mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState,
+        mSavedInstanceState = savedInstanceState;
+        if (isPermissionGranted()) {
+            init(intent, rootView, savedInstanceState);
+        }
+        registerScreenReceiver();
+        // DRM validation
+//        Uri original = intent.getData();
+//        String mimeType = intent.getType();
+//        String filepath = DrmHelper.getFilePath(this, original);
+//        if (DrmHelper.isDrmFile(filepath)) {
+//            if (!DrmHelper.validateLicense(this, filepath, mimeType)) {
+//                finish();
+//            }
+//        }
+    }
+
+    private void init(Intent intent, View rootView, Bundle savedInstanceState) {
+        initMovieInfo(intent);
+        mPlayer = new MoviePlayer(rootView, this, mMovieItem, savedInstanceState,
                 !mFinishOnCompletion) {
             @Override
             public void onCompletion() {
                 if (mFinishOnCompletion) {
-                    finish();
+                    finishActivity();
+                    mControlResumed = false;
+                    Bookmarker mBookmarker = new Bookmarker(MovieActivity.this);
+                    mBookmarker.setBookmark(mMovieItem.getUri(), 0, 1);
                 }
             }
         };
@@ -114,6 +171,37 @@
         // We set the background in the theme to have the launching animation.
         // But for the performance (and battery), we remove the background here.
         win.setBackgroundDrawable(null);
+        initMovieHooker(intent, savedInstanceState);
+
+        mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+            @Override
+            public void onPrepared(MediaPlayer mp) {
+                mPlayer.onPrepared(mp);
+            }
+        });
+    }
+
+    private void initMovieHooker(Intent intent, Bundle savedInstanceState) {
+        mMovieHooker = ExtensionHelper.getHooker(this);
+        mMovieHooker.init(this, intent);
+        mMovieHooker.setParameter(null, mPlayer.getMoviePlayerExt());
+        mMovieHooker.setParameter(null, mMovieItem);
+        mMovieHooker.setParameter(null, mPlayer.getVideoSurface());
+        mMovieHooker.onCreate(savedInstanceState);
+    }
+
+
+    @Override
+    protected void onGetPermissionsSuccess() {
+        init(getIntent(), findViewById(R.id.movie_view_root), mSavedInstanceState);
+        mPlayer.requestAudioFocus();
+        mMovieHooker.onStart();
+        registerScreenReceiver();
+    }
+
+    @Override
+    protected void onGetPermissionsFailure() {
+        finish();
     }
 
     private void setActionBarLogoFromIntent(Intent intent) {
@@ -124,6 +212,10 @@
         }
     }
 
+    public ImageView getLiveImage() {
+        return mLiveImg;
+    }
+
     private void initializeActionBar(Intent intent) {
         mUri = intent.getData();
         final ActionBar actionBar = getActionBar();
@@ -132,9 +224,22 @@
         }
         setActionBarLogoFromIntent(intent);
         actionBar.setDisplayOptions(
-                ActionBar.DISPLAY_HOME_AS_UP,
-                ActionBar.DISPLAY_HOME_AS_UP);
+                ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE,
+                ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE);
+        actionBar.setBackgroundDrawable(new ColorDrawable(Color.argb(66, 0, 0, 0)));
 
+        actionBar.addOnMenuVisibilityListener(new OnMenuVisibilityListener() {
+            @Override
+            public void onMenuVisibilityChanged(boolean isVisible) {
+                if (mPlayer != null) {
+                    if (isVisible) {
+                        mPlayer.cancelHidingController();
+                    } else {
+                        mPlayer.restartHidingController();
+                    }
+                }
+            }
+        });
         String title = intent.getStringExtra(Intent.EXTRA_TITLE);
         if (title != null) {
             actionBar.setTitle(title);
@@ -170,24 +275,49 @@
     public boolean onCreateOptionsMenu(Menu menu) {
         super.onCreateOptionsMenu(menu);
         getMenuInflater().inflate(R.menu.movie, menu);
-
-        // Document says EXTRA_STREAM should be a content: Uri
-        // So, we only share the video if it's "content:".
-        MenuItem shareItem = menu.findItem(R.id.action_share);
-        if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) {
-            shareItem.setVisible(true);
-            ((ShareActionProvider) shareItem.getActionProvider())
-                    .setShareIntent(createShareIntent());
-        } else {
-            shareItem.setVisible(false);
+        MenuItem shareMenu = menu.findItem(R.id.action_share);
+        shareMenu.setVisible(false);
+        if (shareMenu != null) {
+            shareMenu.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    if (mShareIntent != null) {
+                        Intent intent = Intent.createChooser(mShareIntent, null);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        getApplicationContext().startActivity(mShareIntent);
+                    }
+                    return true;
+                }
+            });
         }
+
+        if (isPermissionGranted()) {
+            refreshShareProvider(mMovieItem);
+            mMovieHooker.onCreateOptionsMenu(menu);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        if (mMovieHooker != null) {
+            mMovieHooker.onPrepareOptionsMenu(menu);
+        }
+
+//        if (mMovieItem != null
+//                && !DrmHelper.isShareableDrmFile(DrmHelper.getFilePath(this,
+//                        mMovieItem.getUri()))) {
+//            menu.removeItem(R.id.action_share);
+//        }
+
         return true;
     }
 
     private Intent createShareIntent() {
         Intent intent = new Intent(Intent.ACTION_SEND);
         intent.setType("video/*");
-        intent.putExtra(Intent.EXTRA_STREAM, mUri);
+        intent.putExtra(Intent.EXTRA_STREAM, mMovieItem.getUri());
         return intent;
     }
 
@@ -195,46 +325,90 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         int id = item.getItemId();
         if (id == android.R.id.home) {
-            if (mTreatUpAsBack) {
-                finish();
-            } else {
-                startActivity(new Intent(this, GalleryActivity.class));
-                finish();
-            }
+         // If click back up button, we will always finish current activity and
+         // back to previous one.
+            finish();
             return true;
         } else if (id == R.id.action_share) {
             startActivity(Intent.createChooser(createShareIntent(),
                     getString(R.string.share)));
             return true;
         }
-        return false;
+        return mMovieHooker.onOptionsItemSelected(item);
     }
 
     @Override
     public void onStart() {
-        ((AudioManager) getSystemService(AUDIO_SERVICE))
-                .requestAudioFocus(null, AudioManager.STREAM_MUSIC,
-                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+        if (!isPermissionGranted()) {
+            super.onStart();
+            return;
+        }
+        mPlayer.requestAudioFocus();
         super.onStart();
+        mMovieHooker.onStart();
+
+        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "Gallery_WAKE_LOCK");
+        mWakeLock.acquire();
     }
 
     @Override
     protected void onStop() {
-        ((AudioManager) getSystemService(AUDIO_SERVICE))
-                .abandonAudioFocus(null);
+        if (!isPermissionGranted()) {
+            super.onStop();
+            return;
+        }
+        mPlayer.abandonAudioFocus();
         super.onStop();
+        if (mControlResumed && mPlayer != null) {
+            mPlayer.onStop();
+            mControlResumed = false;
+        }
+        mMovieHooker.onStop();
+
+        mWakeLock.release();
     }
 
     @Override
     public void onPause() {
-        mPlayer.onPause();
+        if (!isPermissionGranted()) {
+            super.onPause();
+            return;
+        }
+        mResumed = false;
+        if (mControlResumed && mPlayer != null) {
+            mControlResumed = !mPlayer.onPause();
+        }
         super.onPause();
+        mMovieHooker.onPause();
     }
 
     @Override
     public void onResume() {
-        mPlayer.onResume();
-        super.onResume();
+        mResumed = true;
+        if (isPermissionGranted()) {
+            invalidateOptionsMenu();
+            if (!isKeyguardLocked() && !mControlResumed && mPlayer != null) {
+                mPlayer.onResume();
+                mControlResumed = true;
+            }
+            enhanceActionBar();
+            super.onResume();
+            mMovieHooker.onResume();
+        } else {
+            super.onResume();
+        }
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if(this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ||
+            this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+            if(mPlayer != null) {
+                mPlayer.setDefaultScreenMode();
+            }
+        }
     }
 
     @Override
@@ -245,8 +419,28 @@
 
     @Override
     public void onDestroy() {
+        if (!isPermissionGranted()) {
+            super.onDestroy();
+            return;
+        }
         mPlayer.onDestroy();
         super.onDestroy();
+        mMovieHooker.onDestroy();
+        unregisterScreenReceiver();
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        if (LOG) {
+            Log.v(TAG, "onWindowFocusChanged(" + hasFocus + ") isKeyguardLocked="
+                    + isKeyguardLocked()
+                    + ", mResumed=" + mResumed + ", mControlResumed=" + mControlResumed);
+        }
+        if (hasFocus && !isKeyguardLocked() && mResumed && !mControlResumed && mPlayer != null) {
+            mPlayer.onResume();
+            mControlResumed = true;
+        }
     }
 
     @Override
@@ -260,4 +454,153 @@
         return mPlayer.onKeyUp(keyCode, event)
                 || super.onKeyUp(keyCode, event);
     }
+
+    private boolean isSharable() {
+        String scheme = mUri.getScheme();
+        return ContentResolver.SCHEME_FILE.equals(scheme)
+                || (ContentResolver.SCHEME_CONTENT.equals(scheme) && MediaStore.AUTHORITY
+                        .equals(mUri.getAuthority()));
+    }
+    private void initMovieInfo(Intent intent) {
+        Uri original = intent.getData();
+        String mimeType = intent.getType();
+        if (VIDEO_SDP_MIME_TYPE.equalsIgnoreCase(mimeType)
+                && VIDEO_FILE_SCHEMA.equalsIgnoreCase(original.getScheme())) {
+            mMovieItem = new MovieItem(VIDEO_SDP_TITLE + original, mimeType, null);
+        } else {
+            mMovieItem = new MovieItem(original, mimeType, null);
+        }
+        mMovieItem.setOriginalUri(original);
+    }
+
+    // we do not stop live streaming when other dialog overlays it.
+    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (LOG) {
+                Log.v(TAG, "onReceive(" + intent.getAction() + ") mControlResumed="
+                        + mControlResumed);
+            }
+            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+                // Only stop video.
+                if (mControlResumed) {
+                    mPlayer.onStop();
+                    mControlResumed = false;
+                }
+            } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+                if (!mControlResumed) {
+                    mPlayer.onResume();
+                    mControlResumed = true;
+                }
+            }
+        }
+
+    };
+
+    private void registerScreenReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(Intent.ACTION_USER_PRESENT);
+        registerReceiver(mScreenReceiver, filter);
+    }
+
+    private void unregisterScreenReceiver() {
+        unregisterReceiver(mScreenReceiver);
+    }
+
+    private boolean isKeyguardLocked() {
+        if (mKeyguardManager == null) {
+            mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+        }
+        // isKeyguardSecure excludes the slide lock case.
+        boolean locked = (mKeyguardManager != null)
+                && mKeyguardManager.inKeyguardRestrictedInputMode();
+        if (LOG) {
+            Log.v(TAG, "isKeyguardLocked() locked=" + locked + ", mKeyguardManager="
+                    + mKeyguardManager);
+        }
+        return locked;
+    }
+
+    public void refreshMovieInfo(IMovieItem info) {
+        mMovieItem = info;
+        setActionBarTitle(info.getTitle());
+        refreshShareProvider(info);
+        mMovieHooker.setParameter(null, mMovieItem);
+    }
+
+    private void refreshShareProvider(IMovieItem info) {
+        // we only share the video if it's "content:".
+        mShareIntent = new Intent(Intent.ACTION_SEND);
+        if (MovieUtils.isLocalFile(info.getUri(), info.getMimeType())) {
+            mShareIntent.setType("video/*");
+            mShareIntent.putExtra(Intent.EXTRA_STREAM, info.getUri());
+        } else {
+            mShareIntent.setType("text/plain");
+            mShareIntent.putExtra(Intent.EXTRA_TEXT, String.valueOf(info.getUri()));
+        }
+    }
+
+    private void enhanceActionBar() {
+        final IMovieItem movieItem = mMovieItem;// remember original item
+        final Uri uri = mMovieItem.getUri();
+        final String scheme = mMovieItem.getUri().getScheme();
+        final String authority = mMovieItem.getUri().getAuthority();
+        new AsyncTask<Void, Void, String>() {
+            @Override
+            protected String doInBackground(Void... params) {
+                String title = null;
+                if (ContentResolver.SCHEME_FILE.equals(scheme)) {
+                    title = MovieTitleHelper.getTitleFromMediaData(MovieActivity.this, uri);
+                } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
+                    title = MovieTitleHelper.getTitleFromDisplayName(MovieActivity.this, uri);
+                    if (title == null) {
+                        title = MovieTitleHelper.getTitleFromData(MovieActivity.this, uri);
+                    }
+                }
+                if (title == null) {
+                    title = MovieTitleHelper.getTitleFromUri(uri);
+                }
+                if (LOG) {
+                    Log.v(TAG, "enhanceActionBar() task return " + title);
+                }
+                return title;
+            }
+
+            @Override
+            protected void onPostExecute(String result) {
+                if (LOG) {
+                    Log.v(TAG, "onPostExecute(" + result + ") movieItem=" + movieItem
+                            + ", mMovieItem=" + mMovieItem);
+                }
+                movieItem.setTitle(result);
+                if (movieItem == mMovieItem) {
+                    setActionBarTitle(result);
+                }
+            };
+        }.execute();
+        if (LOG) {
+            Log.v(TAG, "enhanceActionBar() " + mMovieItem);
+        }
+    }
+
+    public void setActionBarTitle(String title) {
+        if (LOG) {
+            Log.v(TAG, "setActionBarTitle(" + title + ")");
+        }
+        ActionBar actionBar = getActionBar();
+        if (title != null && actionBar != null) {
+            actionBar.setTitle(title);
+        }
+    }
+    @Override
+    public void onBackPressed() {
+        finishActivity();
+    }
+    private void finishActivity(){
+        MovieActivity.this.finish();
+        overridePendingTransition(0,0);
+        return;
+    }
 }
diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java
old mode 100644
new mode 100755
index f01e619..251c3a2
--- a/src/com/android/gallery3d/app/MovieControllerOverlay.java
+++ b/src/com/android/gallery3d/app/MovieControllerOverlay.java
@@ -17,14 +17,34 @@
 package com.android.gallery3d.app;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.media.MediaPlayer;
 import android.os.Handler;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.animation.Animation;
 import android.view.animation.Animation.AnimationListener;
 import android.view.animation.AnimationUtils;
-import com.android.gallery3d.R;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+import android.widget.LinearLayout;
+
+import org.codeaurora.gallery.R;
+
+import org.codeaurora.gallery3d.ext.IContrllerOverlayExt;
+import org.codeaurora.gallery3d.video.IControllerRewindAndForward;
+import org.codeaurora.gallery3d.video.ScreenModeManager;
+import org.codeaurora.gallery3d.video.ScreenModeManager.ScreenModeListener;
+
+import java.util.Locale;
 
 /**
  * The playback controller for the Movie Player.
@@ -32,18 +52,28 @@
 public class MovieControllerOverlay extends CommonControllerOverlay implements
         AnimationListener {
 
+    private static final String TAG = "Gallery3D/MovieControllerOverlay";
+    private static final boolean LOG = false;
+
+    private ScreenModeManager mScreenModeManager;
+    protected ScreenModeExt mScreenModeExt = new ScreenModeExt();
+    protected ControllerRewindAndForwardExt mControllerRewindAndForwardExt = new ControllerRewindAndForwardExt();
+    private OverlayExtension mOverlayExt = new OverlayExtension();
     private boolean hidden;
 
     private final Handler handler;
     private final Runnable startHidingRunnable;
     private final Animation hideAnimation;
 
+    private boolean enableRewindAndForward = false;
+    protected Context mContext;
+
     public MovieControllerOverlay(Context context) {
         super(context);
-
+        mContext = context;
         handler = new Handler();
         startHidingRunnable = new Runnable() {
-                @Override
+            @Override
             public void run() {
                 startHiding();
             }
@@ -52,9 +82,60 @@
         hideAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out);
         hideAnimation.setAnimationListener(this);
 
+        mControllerRewindAndForwardExt.init(context);
+        mScreenModeExt.init(context, mTimeBar);
+        mBackground.setClickable(true);
         hide();
     }
 
+    public void showPlaying() {
+        if (!mOverlayExt.handleShowPlaying()) {
+            mState = State.PLAYING;
+            showMainView(mPlayPauseReplayView);
+        }
+        if (LOG) {
+            Log.v(TAG, "showPlaying() state=" + mState);
+        }
+    }
+
+    public void showPaused() {
+        if (!mOverlayExt.handleShowPaused()) {
+            mState = State.PAUSED;
+            showMainView(mPlayPauseReplayView);
+        }
+        if (LOG) {
+            Log.v(TAG, "showPaused() state=" + mState);
+        }
+    }
+
+    public void showEnded() {
+        mOverlayExt.onShowEnded();
+        mState = State.ENDED;
+        showMainView(mPlayPauseReplayView);
+        if (LOG) {
+            Log.v(TAG, "showEnded() state=" + mState);
+        }
+    }
+
+    public void showLoading() {
+        mOverlayExt.onShowLoading();
+        mState = State.LOADING;
+        showMainView(mLoadingView);
+        if (LOG) {
+            Log.v(TAG, "showLoading() state=" + mState);
+        }
+    }
+
+    public void showErrorMessage(String message) {
+        mOverlayExt.onShowErrorMessage(message);
+        mState = State.ERROR;
+        int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING);
+        mErrorView.setPadding(padding, mErrorView.getPaddingTop(), padding,
+                mErrorView.getPaddingBottom());
+        mErrorView.setText(message);
+        showMainView(mErrorView);
+    }
+
     @Override
     protected void createTimeBar(Context context) {
         mTimeBar = new TimeBar(context, this);
@@ -64,34 +145,66 @@
     public void hide() {
         boolean wasHidden = hidden;
         hidden = true;
-        super.hide();
+        mPlayPauseReplayView.setVisibility(View.INVISIBLE);
+        mLoadingView.setVisibility(View.INVISIBLE);
+        if (!mOverlayExt.handleHide()) {
+            setVisibility(View.INVISIBLE);
+        }
+        mBackground.setVisibility(View.INVISIBLE);
+        mTimeBar.setVisibility(View.INVISIBLE);
+        mScreenModeExt.onHide();
+        if (enableRewindAndForward) {
+            mControllerRewindAndForwardExt.onHide();
+        }
+        setFocusable(true);
+        requestFocus();
         if (mListener != null && wasHidden != hidden) {
             mListener.onHidden();
         }
     }
 
+    private void showMainView(View view) {
+        mMainView = view;
+        mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE
+                : View.INVISIBLE);
+        mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE
+                : View.INVISIBLE);
+        mPlayPauseReplayView
+                .setVisibility(mMainView == mPlayPauseReplayView ? View.VISIBLE
+                        : View.INVISIBLE);
+        mOverlayExt.onShowMainView(view);
+        show();
+    }
 
     @Override
     public void show() {
         boolean wasHidden = hidden;
         hidden = false;
-        super.show();
+        updateViews();
+        setVisibility(View.VISIBLE);
+        setFocusable(false);
         if (mListener != null && wasHidden != hidden) {
             mListener.onShown();
         }
         maybeStartHiding();
     }
 
-    private void maybeStartHiding() {
+    public void maybeStartHiding() {
         cancelHiding();
-        if (mState == State.PLAYING) {
+        if (mState == State.PLAYING || mState == State.PAUSED) {
             handler.postDelayed(startHidingRunnable, 2500);
         }
     }
 
     private void startHiding() {
-        startHideAnimation(mBackground);
-        startHideAnimation(mTimeBar);
+        if (mOverlayExt.canHidePanel()) {
+            startHideAnimation(mBackground);
+            startHideAnimation(mTimeBar);
+            mScreenModeExt.onStartHiding();
+            if (enableRewindAndForward) {
+                mControllerRewindAndForwardExt.onStartHiding();
+            }
+        }
         startHideAnimation(mPlayPauseReplayView);
     }
 
@@ -101,10 +214,16 @@
         }
     }
 
-    private void cancelHiding() {
+    public void cancelHiding() {
         handler.removeCallbacks(startHidingRunnable);
-        mBackground.setAnimation(null);
-        mTimeBar.setAnimation(null);
+        if (mOverlayExt.canHidePanel()) {
+            mBackground.setAnimation(null);
+            mTimeBar.setAnimation(null);
+            mScreenModeExt.onCancelHiding();
+            if (enableRewindAndForward) {
+                mControllerRewindAndForwardExt.onCancelHiding();
+            }
+        }
         mPlayPauseReplayView.setAnimation(null);
     }
 
@@ -123,6 +242,65 @@
         hide();
     }
 
+    public void onClick(View view) {
+        if (LOG) {
+            Log.v(TAG, "onClick(" + view + ") listener=" + mListener
+                    + ", state=" + mState + ", canReplay=" + mCanReplay);
+        }
+        if (mListener != null) {
+            if (view == mPlayPauseReplayView) {
+                if (mState == State.ENDED) {
+                    if (mCanReplay) {
+                        mListener.onReplay();
+                    }
+                } else if (mState == State.PAUSED || mState == State.PLAYING) {
+                    mListener.onPlayPause();
+                    // set view disabled (play/pause asynchronous processing)
+                    setViewEnabled(true);
+                }
+            }
+        } else {
+            mScreenModeExt.onClick(view);
+            if (enableRewindAndForward) {
+                mControllerRewindAndForwardExt.onClick(view);
+            }
+        }
+    }
+
+    /*
+     * set view enable (non-Javadoc)
+     * @see com.android.gallery3d.app.ControllerOverlay#setViewEnabled(boolean)
+     */
+    @Override
+    public void setViewEnabled(boolean isEnabled) {
+        if (mListener.onIsRTSP()) {
+            if (LOG) {
+                Log.v(TAG, "setViewEnabled is " + isEnabled);
+            }
+            mOverlayExt.setCanScrubbing(isEnabled);
+            mPlayPauseReplayView.setEnabled(isEnabled);
+            if (enableRewindAndForward) {
+                mControllerRewindAndForwardExt.setViewEnabled(isEnabled);
+            }
+        }
+    }
+
+    /*
+     * set play pause button from disable to normal (non-Javadoc)
+     * @see
+     * com.android.gallery3d.app.ControllerOverlay#setPlayPauseReplayResume(
+     * void)
+     */
+    @Override
+    public void setPlayPauseReplayResume() {
+        if (mListener.onIsRTSP()) {
+            if (LOG) {
+                Log.v(TAG, "setPlayPauseReplayResume is enabled is true");
+            }
+            mPlayPauseReplayView.setEnabled(true);
+        }
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (hidden) {
@@ -144,7 +322,10 @@
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
                 cancelHiding();
-                if (mState == State.PLAYING || mState == State.PAUSED) {
+                // you can click play or pause when view is resumed
+                // play/pause asynchronous processing
+                if ((mState == State.PLAYING || mState == State.PAUSED)
+                        && mOverlayExt.mEnableScrubbing) {
                     mListener.onPlayPause();
                 }
                 break;
@@ -156,11 +337,76 @@
     }
 
     @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int width = ((MovieActivity) mContext).getWindowManager().getDefaultDisplay().getWidth();
+        Rect insets = mWindowInsets;
+        int pl = insets.left; // the left paddings
+        int pr = insets.right;
+        int pt = insets.top;
+        int pb = insets.bottom;
+
+        int h = bottom - top;
+        int w = right - left;
+        boolean error = mErrorView.getVisibility() == View.VISIBLE;
+
+        int y = h - pb;
+        // Put both TimeBar and Background just above the bottom system
+        // component.
+        // But extend the background to the width of the screen, since we don't
+        // care if it will be covered by a system component and it looks better.
+
+        // Needed, otherwise the framework will not re-layout in case only the
+        // padding is changed
+        if (enableRewindAndForward) {
+            mBackground.layout(0, y - mTimeBar.getPreferredHeight() - 80, w, y);
+            mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight() - 120, w - pr,
+                    y - mTimeBar.getBarHeight());
+            mControllerRewindAndForwardExt.onLayout(0, width, y);
+        } else {
+            mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y);
+            mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(),
+                    w - pr - mScreenModeExt.getAddedRightPadding(), y);
+        }
+        mScreenModeExt.onLayout(w, pr, y);
+        // Put the play/pause/next/ previous button in the center of the screen
+        layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
+
+        if (mMainView != null) {
+            layoutCenteredView(mMainView, 0, 0, w, h);
+        }
+    }
+
+    @Override
     protected void updateViews() {
         if (hidden) {
             return;
         }
-        super.updateViews();
+        mBackground.setVisibility(View.VISIBLE);
+        mTimeBar.setVisibility(View.VISIBLE);
+        mPlayPauseReplayView.setImageResource(
+                mState == State.PAUSED ? R.drawable.videoplayer_play :
+                        mState == State.PLAYING ? R.drawable.videoplayer_pause :
+                                R.drawable.videoplayer_reload);
+        Resources resources = getContext().getResources();
+        mPlayPauseReplayView.setContentDescription(
+                mState == State.PAUSED ? resources.getString(R.string.accessibility_play_video) :
+                        mState == State.PLAYING ? resources.getString(R.string.accessibility_pause_video) :
+                                resources.getString(R.string.accessibility_reload_video));
+        mScreenModeExt.onShow();
+        if (enableRewindAndForward) {
+            mControllerRewindAndForwardExt.onShow();
+        }
+        if (!mOverlayExt.handleUpdateViews()) {
+            mPlayPauseReplayView.setVisibility(
+                    (mState != State.LOADING && mState != State.ERROR &&
+                    !(mState == State.ENDED && !mCanReplay))
+                            ? View.VISIBLE : View.GONE);
+        }
+        requestLayout();
+        if (LOG) {
+            Log.v(TAG, "updateViews() state=" + mState + ", canReplay="
+                    + mCanReplay);
+        }
     }
 
     // TimeBar listener
@@ -182,4 +428,583 @@
         maybeStartHiding();
         super.onScrubbingEnd(time, trimStartTime, trimEndTime);
     }
+
+    public void setScreenModeManager(ScreenModeManager manager) {
+        mScreenModeManager = manager;
+        if (mScreenModeManager != null) {
+            mScreenModeManager.addListener(mScreenModeExt);
+        }
+        if (LOG) {
+            Log.v(TAG, "setScreenModeManager(" + manager + ")");
+        }
+    }
+
+    public void setDefaultScreenMode() {
+        mScreenModeManager.setScreenMode(ScreenModeManager.SCREENMODE_BIGSCREEN);
+    }
+
+    private void updateBackgroundColor() {
+        switch (mState) {
+            case PAUSED:
+            case PLAYING:
+            case BUFFERING:
+                setBackgroundColor(Color.TRANSPARENT);
+                break;
+            default:
+                setBackgroundColor(Color.BLACK);
+        }
+    }
+
+    public IContrllerOverlayExt getOverlayExt() {
+        return mOverlayExt;
+    }
+
+    public IControllerRewindAndForward getControllerRewindAndForwardExt() {
+        if (enableRewindAndForward) {
+            return mControllerRewindAndForwardExt;
+        }
+        return null;
+    }
+
+    private class OverlayExtension implements IContrllerOverlayExt {
+        private State mLastState = State.LOADING;
+        private String mPlayingInfo;
+        // for pause feature
+        private boolean mCanPause = true;
+        private boolean mEnableScrubbing = false;
+        // for only audio feature
+        private boolean mAlwaysShowBottom;
+
+        @Override
+        public void showBuffering(int what) {
+            if (mState == State.PAUSED || mState == State.PLAYING) {
+                mLastState = mState;
+            }
+            if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START) {
+                mState = State.BUFFERING;
+                showMainView(mLoadingView);
+            } else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END || what == TimeBar.UNKNOWN) {
+                mState = mLastState;
+                showMainView(mPlayPauseReplayView);
+            }
+        }
+
+        // set buffer percent to unknown value
+        public void clearBuffering() {
+            if (LOG) {
+                Log.v(TAG, "clearBuffering()");
+            }
+            mTimeBar.setSecondaryProgress(TimeBar.UNKNOWN);
+            showBuffering(TimeBar.UNKNOWN);
+        }
+
+        public void showReconnecting(int times) {
+            clearBuffering();
+            mState = State.RETRY_CONNECTING;
+            int msgId = R.string.videoview_error_text_cannot_connect_retry;
+            String text = getResources().getString(msgId, times);
+            mTimeBar.setInfo(text);
+            showMainView(mLoadingView);
+            if (LOG) {
+                Log.v(TAG, "showReconnecting(" + times + ")");
+            }
+        }
+
+        public void showReconnectingError() {
+            clearBuffering();
+            mState = State.RETRY_CONNECTING_ERROR;
+
+            String text = "can not connect to server";
+            mTimeBar.setInfo(text);
+            showMainView(mPlayPauseReplayView);
+            if (LOG) {
+                Log.v(TAG, "showReconnectingError()");
+            }
+        }
+
+        public void setPlayingInfo(boolean liveStreaming) {
+            int msgId;
+            // TODO
+            if (liveStreaming) {
+                msgId = R.string.media_controller_live;
+            } else {
+                msgId = R.string.media_controller_playing;
+            }
+            mPlayingInfo = getResources().getString(msgId);
+            if (LOG) {
+                Log.v(TAG, "setPlayingInfo(" + liveStreaming
+                        + ") playingInfo=" + mPlayingInfo);
+            }
+        }
+
+        public void setCanPause(boolean canPause) {
+            this.mCanPause = canPause;
+            if (LOG) {
+                Log.v(TAG, "setCanPause(" + canPause + ")");
+            }
+        }
+
+        public void setCanScrubbing(boolean enable) {
+            mEnableScrubbing = enable;
+            mTimeBar.setScrubbing(enable);
+            if (LOG) {
+                Log.v(TAG, "setCanScrubbing(" + enable + ")");
+            }
+        }
+
+        public void setBottomPanel(boolean alwaysShow, boolean foreShow) {
+            mAlwaysShowBottom = alwaysShow;
+            if (!alwaysShow) { // clear background
+                setBackgroundDrawable(null);
+                updateBackgroundColor();
+            } else {
+                setBackgroundResource(R.drawable.media_default_bkg);
+                if (foreShow) {
+                    setVisibility(View.VISIBLE);
+                }
+            }
+            if (LOG) {
+                Log.v(TAG, "setBottomPanel(" + alwaysShow + ", " + foreShow
+                        + ")");
+            }
+        }
+
+        public boolean isPlayingEnd() {
+            if (LOG) {
+                Log.v(TAG, "isPlayingEnd() state=" + mState);
+            }
+            boolean end = false;
+            if (State.ENDED == mState || State.ERROR == mState
+                    || State.RETRY_CONNECTING_ERROR == mState) {
+                end = true;
+            }
+            return end;
+        }
+
+        public boolean handleShowPlaying() {
+            if (mState == State.BUFFERING) {
+                mLastState = State.PLAYING;
+                return true;
+            }
+            return false;
+        }
+
+        public boolean handleShowPaused() {
+            mTimeBar.setInfo(null);
+            if (mState == State.BUFFERING) {
+                mLastState = State.PAUSED;
+                return true;
+            }
+            return false;
+        }
+
+        public void onShowLoading() {
+            // TODO
+            int msgId = R.string.media_controller_connecting;
+            String text = getResources().getString(msgId);
+            mTimeBar.setInfo(text);
+        }
+
+        public void onShowEnded() {
+            clearBuffering();
+            mTimeBar.setInfo(null);
+        }
+
+        public void onShowErrorMessage(String message) {
+            clearBuffering();
+        }
+
+        public boolean handleUpdateViews() {
+            mPlayPauseReplayView
+                    .setVisibility((mState != State.LOADING
+                            && mState != State.ERROR
+                            && mState != State.BUFFERING
+                            && mState != State.RETRY_CONNECTING && !(mState != State.ENDED
+                            && mState != State.RETRY_CONNECTING_ERROR && !mCanPause))
+                            // for live streaming
+                            ? View.VISIBLE
+                            : View.GONE);
+
+            if (mPlayingInfo != null && mState == State.PLAYING) {
+                mTimeBar.setInfo(mPlayingInfo);
+            }
+            return true;
+        }
+
+        public boolean handleHide() {
+            return mAlwaysShowBottom;
+        }
+
+        public void onShowMainView(View view) {
+            if (LOG) {
+                Log.v(TAG, "showMainView(" + view + ") errorView="
+                        + mErrorView + ", loadingView=" + mLoadingView
+                        + ", playPauseReplayView=" + mPlayPauseReplayView);
+                Log.v(TAG, "showMainView() enableScrubbing="
+                        + mEnableScrubbing + ", state=" + mState);
+            }
+            if (mEnableScrubbing
+                    && (mState == State.PAUSED || mState == State.PLAYING)) {
+                mTimeBar.setScrubbing(true);
+            } else {
+                mTimeBar.setScrubbing(false);
+            }
+        }
+
+        public boolean canHidePanel() {
+            return !mAlwaysShowBottom;
+        }
+    };
+
+    class ScreenModeExt implements View.OnClickListener, ScreenModeListener {
+        // for screen mode feature
+        private ImageView mScreenView;
+        private int mScreenPadding;
+        private int mScreenWidth;
+
+        private static final int MARGIN = 10; // dip
+        private ViewGroup mParent;
+        private ImageView mSeprator;
+
+        void init(Context context, View myTimeBar) {
+            DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+            int padding = (int) (metrics.density * MARGIN);
+            myTimeBar.setPadding(padding, 0, padding, 0);
+
+            LayoutParams wrapContent =
+                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+            // add screenView
+            mScreenView = new ImageView(context, null, android.R.attr.actionButtonStyle);
+            // default next screen mode
+            mScreenView.setImageResource(R.drawable.ic_media_fullscreen);
+            mScreenView.setScaleType(ScaleType.CENTER);
+            mScreenView.setFocusable(true);
+            mScreenView.setClickable(true);
+            mScreenView.setOnClickListener(this);
+            addView(mScreenView, wrapContent);
+
+            if (enableRewindAndForward) {
+                if (LOG) {
+                    Log.v(TAG, "ScreenModeExt enableRewindAndForward");
+                }
+                mSeprator = new ImageView(context);
+                // default next screen mode
+                mSeprator.setImageResource(R.drawable.ic_separator_line);
+                mSeprator.setScaleType(ScaleType.CENTER);
+                mSeprator.setFocusable(true);
+                mSeprator.setClickable(true);
+                mSeprator.setOnClickListener(this);
+                addView(mSeprator, wrapContent);
+
+            } else {
+                if (LOG) {
+                    Log.v(TAG, "ScreenModeExt unenableRewindAndForward");
+                }
+            }
+
+            // for screen layout
+            Drawable screenButton = context.getResources()
+                    .getDrawable(R.drawable.ic_media_bigscreen, null);
+            if (screenButton != null) {
+                mScreenWidth = screenButton.getIntrinsicWidth();
+            }
+            mScreenPadding = (int) (metrics.density * MARGIN);
+        }
+
+        private void updateScreenModeDrawable() {
+            int screenMode = mScreenModeManager.getNextScreenMode();
+            if (screenMode == ScreenModeManager.SCREENMODE_BIGSCREEN) {
+                mScreenView.setImageResource(R.drawable.ic_media_bigscreen);
+            } else if (screenMode == ScreenModeManager.SCREENMODE_FULLSCREEN) {
+                mScreenView.setImageResource(R.drawable.ic_media_fullscreen);
+            } else {
+                mScreenView.setImageResource(R.drawable.ic_media_cropscreen);
+            }
+        }
+
+        @Override
+        public void onClick(View v) {
+            if (v == mScreenView && mScreenModeManager != null) {
+                mScreenModeManager.setScreenMode(mScreenModeManager
+                        .getNextScreenMode());
+                show();
+            }
+        }
+
+        public void onStartHiding() {
+            startHideAnimation(mScreenView);
+        }
+
+        public void onCancelHiding() {
+            mScreenView.setAnimation(null);
+        }
+
+        public void onHide() {
+            mScreenView.setVisibility(View.INVISIBLE);
+            if (enableRewindAndForward) {
+                mSeprator.setVisibility(View.INVISIBLE);
+            }
+        }
+
+        public void onShow() {
+            mScreenView.setVisibility(View.VISIBLE);
+            if (enableRewindAndForward) {
+                mSeprator.setVisibility(View.VISIBLE);
+            }
+        }
+
+        public void onLayout(int width, int paddingRight, int yPosition) {
+            // layout screen view position
+            int sw = getAddedRightPadding();
+            mScreenView.layout(width - paddingRight - sw, yPosition
+                    - mTimeBar.getPreferredHeight(), width - paddingRight,
+                    yPosition);
+            if (enableRewindAndForward) {
+                mSeprator.layout(width - paddingRight - sw - 22, yPosition
+                        - mTimeBar.getPreferredHeight(), width - paddingRight - sw - 20,
+                        yPosition);
+            }
+        }
+
+        public int getAddedRightPadding() {
+            return mScreenWidth;
+        }
+
+        @Override
+        public void onScreenModeChanged(int newMode) {
+            updateScreenModeDrawable();
+        }
+    }
+
+    class ControllerRewindAndForwardExt implements View.OnClickListener,
+            IControllerRewindAndForward {
+        private LinearLayout mContollerButtons;
+        private ImageView mStop;
+        private ImageView mForward;
+        private ImageView mRewind;
+        private IRewindAndForwardListener mListenerForRewind;
+        private int mButtonWidth;
+        private static final int BUTTON_PADDING = 40;
+        private int mTimeBarHeight = 0;
+
+        public ImageView getStopBtn() {
+            return mStop;
+        }
+
+        void init(Context context) {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt init");
+            }
+            mTimeBarHeight = mTimeBar.getPreferredHeight();
+
+            Drawable forwardMenu = context.getResources().
+                    getDrawable(R.drawable.ic_menu_forward, null);
+            if (forwardMenu != null) {
+                mButtonWidth = forwardMenu.getIntrinsicWidth();
+            }
+
+            mContollerButtons = new LinearLayout(context);
+            LinearLayout.LayoutParams wrapContent = new LinearLayout.LayoutParams(
+                    getAddedRightPadding(), mTimeBarHeight);
+            mContollerButtons.setHorizontalGravity(LinearLayout.HORIZONTAL);
+            mContollerButtons.setVisibility(View.VISIBLE);
+            mContollerButtons.setGravity(Gravity.CENTER);
+
+            LinearLayout.LayoutParams buttonParam = new LinearLayout.LayoutParams(
+                    mButtonWidth, mTimeBarHeight);
+            mRewind = new ImageView(context);
+            mRewind.setImageResource(R.drawable.icn_media_rewind);
+            mRewind.setScaleType(ScaleType.CENTER);
+            mRewind.setFocusable(true);
+            mRewind.setClickable(true);
+            mRewind.setOnClickListener(this);
+            mContollerButtons.addView(mRewind, buttonParam);
+
+            mStop = new ImageView(context);
+            mStop.setImageResource(R.drawable.icn_media_stop);
+            mStop.setScaleType(ScaleType.CENTER);
+            mStop.setFocusable(true);
+            mStop.setClickable(true);
+            mStop.setOnClickListener(this);
+            LinearLayout.LayoutParams stopLayoutParam = new LinearLayout.LayoutParams(
+                    mTimeBarHeight, mTimeBarHeight);
+            stopLayoutParam.setMargins(BUTTON_PADDING, 0, BUTTON_PADDING, 0);
+
+            mForward = new ImageView(context);
+            mForward.setImageResource(R.drawable.icn_media_forward);
+            mForward.setScaleType(ScaleType.CENTER);
+            mForward.setFocusable(true);
+            mForward.setClickable(true);
+            mForward.setOnClickListener(this);
+            mContollerButtons.addView(mForward, buttonParam);
+
+            // Do NOT RTL for media controller
+            mContollerButtons.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+
+            addView(mContollerButtons, wrapContent);
+        }
+
+        @Override
+        public void onClick(View v) {
+            if (v == mStop) {
+                if (LOG) {
+                    Log.v(TAG, "ControllerRewindAndForwardExt onClick mStop");
+                }
+                mListenerForRewind.onStopVideo();
+            } else if (v == mRewind) {
+                if (LOG) {
+                    Log.v(TAG, "ControllerRewindAndForwardExt onClick mRewind");
+                }
+                if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+                        == View.LAYOUT_DIRECTION_RTL) {
+                    mListenerForRewind.onForward();
+                } else {
+                    mListenerForRewind.onRewind();
+                }
+            } else if (v == mForward) {
+                if (LOG) {
+                    Log.v(TAG, "ControllerRewindAndForwardExt onClick mForward");
+                }
+                if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
+                        == View.LAYOUT_DIRECTION_RTL) {
+                    mListenerForRewind.onRewind();
+                } else {
+                    mListenerForRewind.onForward();
+                }
+            }
+        }
+
+        public void onStartHiding() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onStartHiding");
+            }
+            startHideAnimation(mContollerButtons);
+        }
+
+        public void onCancelHiding() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onCancelHiding");
+            }
+            mContollerButtons.setAnimation(null);
+        }
+
+        public void onHide() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onHide");
+            }
+            mContollerButtons.setVisibility(View.INVISIBLE);
+        }
+
+        public void onShow() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onShow: " + mState);
+            }
+            mContollerButtons.setVisibility(View.VISIBLE);
+            updateBackgroundColor();
+        }
+
+        public void onLayout(int l, int r, int b) {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onLayout");
+            }
+            int cl = (r - l - getAddedRightPadding()) / 2;
+            int cr = cl + getAddedRightPadding();
+            mContollerButtons.layout(cl, b - mTimeBar.getPreferredHeight(), cr, b);
+        }
+
+        public int getAddedRightPadding() {
+            return mTimeBarHeight * 3 + BUTTON_PADDING * 2;
+        }
+
+        @Override
+        public void setIListener(IRewindAndForwardListener listener) {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt setIListener " + listener);
+            }
+            mListenerForRewind = listener;
+        }
+
+        @Override
+        public void showControllerButtonsView(boolean canStop, boolean canRewind, boolean canForward) {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt showControllerButtonsView " + canStop
+                    + canRewind + canForward);
+            }
+            // show ui
+            mStop.setEnabled(canStop);
+            mRewind.setEnabled(canRewind);
+            mForward.setEnabled(canForward);
+        }
+
+        @Override
+        public void setListener(Listener listener) {
+            setListener(listener);
+        }
+
+        @Override
+        public boolean getPlayPauseEanbled() {
+            return mPlayPauseReplayView.isEnabled();
+        }
+
+        @Override
+        public boolean getTimeBarEanbled() {
+            return mTimeBar.getScrubbing();
+        }
+
+        @Override
+        public void setCanReplay(boolean canReplay) {
+            setCanReplay(canReplay);
+        }
+
+        @Override
+        public View getView() {
+            return mContollerButtons;
+        }
+
+        @Override
+        public void show() {
+            show();
+        }
+
+        @Override
+        public void showPlaying() {
+            showPlaying();
+        }
+
+        @Override
+        public void showPaused() {
+            showPaused();
+        }
+
+        @Override
+        public void showEnded() {
+            showEnded();
+        }
+
+        @Override
+        public void showLoading() {
+            showLoading();
+        }
+
+        @Override
+        public void showErrorMessage(String message) {
+            showErrorMessage(message);
+        }
+
+        public void setTimes(int currentTime, int totalTime, int trimStartTime, int trimEndTime) {
+            setTimes(currentTime, totalTime, 0, 0);
+        }
+
+        public void setPlayPauseReplayResume() {
+        }
+
+        public void setViewEnabled(boolean isEnabled) {
+            // TODO Auto-generated method stub
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt setViewEnabled is " + isEnabled);
+            }
+            mRewind.setEnabled(isEnabled);
+            mForward.setEnabled(isEnabled);
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/app/MovieControllerOverlayNew.java b/src/com/android/gallery3d/app/MovieControllerOverlayNew.java
new file mode 100644
index 0000000..6d127bb
--- /dev/null
+++ b/src/com/android/gallery3d/app/MovieControllerOverlayNew.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import org.codeaurora.gallery3d.video.IVideoSnapshotListener;
+import org.codeaurora.gallery3d.video.IControllerRewindAndForward;
+
+import org.codeaurora.gallery.R;
+
+public class MovieControllerOverlayNew extends MovieControllerOverlay {
+    private VideoSnapshotLayout mVideoSnapshotLayout = new VideoSnapshotLayout();
+    private IVideoSnapshotListener mVideoSnapshotListener;
+
+    private boolean mIsLive = false;
+    private ImageView mLiveImage;
+    private ImageView mStopBtn;
+
+    private int mLiveMargin;
+
+    public MovieControllerOverlayNew(Context context) {
+        super(context);
+
+        mVideoSnapshotLayout.init(context);
+        mLiveImage = ((MovieActivity) mContext).getLiveImage();
+        mStopBtn = mControllerRewindAndForwardExt.getStopBtn();
+        mLiveMargin = context.getResources().getDimensionPixelSize(
+                R.dimen.livestream_icon_padding);
+        addView(mStopBtn);
+    }
+
+    @Override
+    protected void createTimeBar(Context context) {
+        mTimeBar = new TimeBarNew(context, this);
+    }
+
+    public TimeBar getTimeBar() {
+        return mTimeBar;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return false;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int width = ((MovieActivity) mContext).getWindowManager().getDefaultDisplay().getWidth();
+        Rect insets = mWindowInsets;
+        int pr = insets.right;
+        int pb = insets.bottom;
+        int pt = insets.top;
+        int h = bottom - top;
+        int w = right - left;
+
+        int y = h - pb;
+        int barHeight = mTimeBar.getPreferredHeight();
+
+        mBackground.layout(0, y - barHeight, w, y);
+        mScreenModeExt.onLayout(w, pr, y);
+        if (mIsLive && mState != State.ENDED) {
+            if (mLiveImage != null) {
+                mLiveImage.setPadding(mLiveImage.getPaddingLeft(), mLiveMargin + pt,
+                        mLiveMargin + pr, mLiveImage.getPaddingBottom());
+                mLiveImage.setVisibility(View.VISIBLE);
+            }
+            if (isPrepared()) {
+                mPlayPauseReplayView.setVisibility(View.GONE);
+
+                if (mStopBtn != null) {
+                    mStopBtn.setVisibility(View.VISIBLE);
+                    mStopBtn.layout(0, y - barHeight, barHeight, y);
+                }
+            }
+        } else {
+            mPlayPauseReplayView.setVisibility(View.VISIBLE);
+            if (mLiveImage != null) {
+                mLiveImage.setVisibility(View.GONE);
+            }
+            if (mStopBtn != null) {
+                mStopBtn.setVisibility(View.GONE);
+            }
+            // Put the play/pause/next/previous button in the center of the screen
+            layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h);
+        }
+        mTimeBar.layout(insets.left + barHeight, y - barHeight,
+                width - mScreenModeExt.getAddedRightPadding(), y);
+
+        mVideoSnapshotLayout.layoutButton(
+                w - pr - mVideoSnapshotLayout.getButtonWidth(),
+                y - barHeight - mVideoSnapshotLayout.getButtonHeight(),
+                w - pr,
+                y - barHeight);
+        mVideoSnapshotLayout.layoutAnim(left, top, right, bottom);
+    }
+
+    public void setLive(boolean live) {
+        mIsLive = live;
+        mTimeBar.setClickable(!mIsLive);
+    }
+
+    @Override
+    public IControllerRewindAndForward getControllerRewindAndForwardExt() {
+        return mControllerRewindAndForwardExt;
+    }
+
+    private boolean isPrepared() {
+        if ((mState == State.PLAYING || mState == State.BUFFERING || mState == State.LOADING)) {
+            return true;
+        }
+        return false;
+    }
+
+    public void setVideoSnapshotListener(IVideoSnapshotListener listener) {
+        mVideoSnapshotListener = listener;
+    }
+
+    public void showVideoSnapshotButton(boolean show) {
+        if (mVideoSnapshotLayout != null) {
+            mVideoSnapshotLayout.showVideoSnapshotButton(show);
+        }
+    }
+
+    class VideoSnapshotLayout implements View.OnClickListener {
+        private ImageView mVideoSnapshotButton;
+        private ImageView mVideoSnapshotAnimView;
+        private Animation mVideoSnapshotAnimation;
+
+        public void init(Context context) {
+            LayoutParams wrapContent =
+                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+            mVideoSnapshotButton = new ImageView(context);
+            mVideoSnapshotButton.setImageResource(R.drawable.ic_video_snapshot_selector);
+            mVideoSnapshotButton.setScaleType(ImageView.ScaleType.CENTER);
+            mVideoSnapshotButton.setFocusable(true);
+            mVideoSnapshotButton.setClickable(true);
+            mVideoSnapshotButton.setOnClickListener(this);
+            addView(mVideoSnapshotButton, wrapContent);
+
+            LayoutParams matchParent =
+                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+            mVideoSnapshotAnimView = new ImageView(context);
+            addView(mVideoSnapshotAnimView, matchParent);
+
+            mVideoSnapshotAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out);
+            mVideoSnapshotAnimation.setAnimationListener(new Animation.AnimationListener() {
+                @Override
+                public void onAnimationStart(Animation animation) {
+                    mVideoSnapshotAnimView.setBackgroundColor(Color.WHITE);
+                    mVideoSnapshotButton.setEnabled(false);
+                }
+
+                @Override
+                public void onAnimationEnd(Animation animation) {
+                    mVideoSnapshotAnimView.setBackgroundColor(Color.TRANSPARENT);
+                    mVideoSnapshotButton.setEnabled(true);
+                }
+
+                @Override
+                public void onAnimationRepeat(Animation animation) {
+                }
+            });
+        }
+
+        public int getButtonWidth() {
+            return mVideoSnapshotButton == null ? 0 : mVideoSnapshotButton.getMeasuredWidth();
+        }
+
+        public int getButtonHeight() {
+            return mVideoSnapshotButton == null ? 0 : mVideoSnapshotButton.getMeasuredHeight();
+        }
+
+        public void layoutButton(int l, int t, int r, int b) {
+            if (mVideoSnapshotButton != null) {
+                mVideoSnapshotButton.layout(l, t, r, b);
+            }
+        }
+
+        public void layoutAnim(int l, int t, int r, int b) {
+            if (mVideoSnapshotAnimView != null) {
+                mVideoSnapshotAnimView.layout(l, t, r, b);
+            }
+        }
+
+        public void showVideoSnapshotButton(boolean show) {
+            if (mVideoSnapshotButton != null) {
+                mVideoSnapshotButton.setVisibility(show ? VISIBLE : GONE);
+            }
+        }
+
+        @Override
+        public void onClick(View v) {
+            maybeStartHiding();
+            if (mVideoSnapshotListener != null && mVideoSnapshotListener.canVideoSnapshot()) {
+                mVideoSnapshotListener.onVideoSnapshot();
+                startAnimation();
+            }
+        }
+
+        private void startAnimation() {
+            if (mVideoSnapshotAnimView != null) {
+                mVideoSnapshotAnimView.startAnimation(mVideoSnapshotAnimation);
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java
old mode 100644
new mode 100755
index f6bd367..7db8dcf
--- a/src/com/android/gallery3d/app/MoviePlayer.java
+++ b/src/com/android/gallery3d/app/MoviePlayer.java
@@ -23,11 +23,14 @@
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnShowListener;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.graphics.Color;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
-import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Virtualizer;
 import android.net.Uri;
 import android.os.Build;
@@ -35,26 +38,48 @@
 import android.os.Handler;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
+import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.VideoView;
+import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.BlobCache;
 import com.android.gallery3d.util.CacheManager;
 import com.android.gallery3d.util.GalleryUtils;
 
+import org.codeaurora.gallery3d.ext.IContrllerOverlayExt;
+import org.codeaurora.gallery3d.ext.IMovieItem;
+import org.codeaurora.gallery3d.ext.IMoviePlayer;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+import org.codeaurora.gallery3d.video.BookmarkEnhance;
+import org.codeaurora.gallery3d.video.CodeauroraVideoView;
+import org.codeaurora.gallery3d.video.IControllerRewindAndForward;
+import org.codeaurora.gallery3d.video.IControllerRewindAndForward.IRewindAndForwardListener;
+import org.codeaurora.gallery3d.video.ScreenModeManager;
+import org.codeaurora.gallery3d.video.ScreenModeManager.ScreenModeListener;
+import org.codeaurora.gallery3d.video.VideoSnapshotExt;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Timer;
 
 public class MoviePlayer implements
         MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener,
-        ControllerOverlay.Listener {
+        ControllerOverlay.Listener,
+        MediaPlayer.OnInfoListener,
+        MediaPlayer.OnPreparedListener,
+        MediaPlayer.OnSeekCompleteListener,
+        MediaPlayer.OnVideoSizeChangedListener,
+        MediaPlayer.OnBufferingUpdateListener {
     @SuppressWarnings("unused")
     private static final String TAG = "MoviePlayer";
+    private static final boolean LOG = false;
 
     private static final String KEY_VIDEO_POSITION = "video-position";
     private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout";
@@ -68,25 +93,44 @@
     private static final String CMDNAME = "command";
     private static final String CMDPAUSE = "pause";
 
+    private static final String KEY_VIDEO_CAN_SEEK = "video_can_seek";
+    private static final String KEY_VIDEO_CAN_PAUSE = "video_can_pause";
+    private static final String KEY_VIDEO_LAST_DURATION = "video_last_duration";
+    private static final String KEY_VIDEO_LAST_DISCONNECT_TIME = "last_disconnect_time";
+    private static final String KEY_VIDEO_STREAMING_TYPE = "video_streaming_type";
+    private static final String KEY_VIDEO_STATE = "video_state";
+
     private static final String VIRTUALIZE_EXTRA = "virtualize";
-    private static final long BLACK_TIMEOUT = 500;
+    public static final int SERVER_TIMEOUT = 8801;
 
     // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing.
     // Otherwise, we pause the player.
     private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins
 
+    public static final int STREAMING_LOCAL = 0;
+    public static final int STREAMING_HTTP = 1;
+    public static final int STREAMING_RTSP = 2;
+    public static final int STREAMING_SDP = 3;
+    private int mStreamingType = STREAMING_LOCAL;
+
     private Context mContext;
-    private final VideoView mVideoView;
+    private final CodeauroraVideoView mVideoView;
+    private final View mCoverView;
     private final View mRootView;
     private final Bookmarker mBookmarker;
-    private final Uri mUri;
     private final Handler mHandler = new Handler();
     private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver;
-    private final MovieControllerOverlay mController;
+    private final MovieControllerOverlayNew mController;
+    private final GestureControllerOverlay mGestureController;
 
     private long mResumeableTime = Long.MAX_VALUE;
     private int mVideoPosition = 0;
     private boolean mHasPaused = false;
+    private boolean mVideoHasPaused = false;
+    private boolean mCanResumed = false;
+    private boolean mFirstBePlayed = false;
+    private boolean mKeyguardLocked = false;
+    private boolean mIsOnlyAudio = false;
     private int mLastSystemUiVis = 0;
 
     // If the time bar is being dragged.
@@ -95,8 +139,43 @@
     // If the time bar is visible.
     private boolean mShowing;
 
+    // used to track what type of audio focus loss caused the video to pause
+    private boolean mPausedByTransientLossOfFocus = false;
+
     private Virtualizer mVirtualizer;
 
+    private MovieActivity mActivityContext;//for dialog and toast context
+    private MoviePlayerExtension mPlayerExt = new MoviePlayerExtension();
+    private RetryExtension mRetryExt = new RetryExtension();
+    private ServerTimeoutExtension mServerTimeoutExt = new ServerTimeoutExtension();
+    private ScreenModeExt mScreenModeExt = new ScreenModeExt();
+    private IContrllerOverlayExt mOverlayExt;
+    private IControllerRewindAndForward mControllerRewindAndForwardExt;
+    private IRewindAndForwardListener mRewindAndForwardListener = new ControllerRewindAndForwardExt();
+    private boolean mCanReplay;
+    private boolean mVideoCanSeek = false;
+    private boolean mVideoCanPause = false;
+    private boolean mWaitMetaData;
+    private boolean mIsShowResumingDialog;
+    private TState mTState = TState.PLAYING;
+    private IMovieItem mMovieItem;
+    private int mVideoLastDuration;//for duration displayed in init state
+
+    private VideoSnapshotExt mVideoSnapshotExt = new VideoSnapshotExt();
+
+    private enum TState {
+        PLAYING,
+        PAUSED,
+        STOPED,
+        COMPELTED,
+        RETRY_ERROR
+    }
+
+    interface Restorable {
+        void onRestoreInstanceState(Bundle icicle);
+        void onSaveInstanceState(Bundle outState);
+    }
+
     private final Runnable mPlayingChecker = new Runnable() {
         @Override
         public void run() {
@@ -116,22 +195,66 @@
         }
     };
 
+    public interface TimerProgress {
+        void startTimer();
+    }
+
+    private TimerProgress mTimerController = new TimerProgress() {
+        @Override
+        public void startTimer() {
+            mHandler.removeCallbacks(mProgressChecker);
+            mHandler.post(mProgressChecker);
+        }
+    };
+
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+                mKeyguardLocked = true;
+            } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
+                if ((mCanResumed) && (!mVideoHasPaused)) {
+                    playVideo();
+                }
+                mKeyguardLocked = false;
+                mCanResumed = false;
+            } else if (Intent.ACTION_SHUTDOWN.equals(intent.getAction())) {
+                if (LOG) {
+                    Log.v(TAG, "Intent.ACTION_SHUTDOWN received");
+                }
+                mActivityContext.finish();
+            }
+        }
+    };
+
     public MoviePlayer(View rootView, final MovieActivity movieActivity,
-            Uri videoUri, Bundle savedInstance, boolean canReplay) {
+            IMovieItem info, Bundle savedInstance, boolean canReplay) {
         mContext = movieActivity.getApplicationContext();
         mRootView = rootView;
-        mVideoView = (VideoView) rootView.findViewById(R.id.surface_view);
+        mVideoView = (CodeauroraVideoView) rootView.findViewById(R.id.surface_view);
+        mCoverView = rootView.findViewById(R.id.surface_view_cover);
         mBookmarker = new Bookmarker(movieActivity);
-        mUri = videoUri;
 
-        mController = new MovieControllerOverlay(mContext);
-        ((ViewGroup)rootView).addView(mController.getView());
+        mController = new MovieControllerOverlayNew(movieActivity);
+
+        mGestureController = new GestureControllerOverlay(movieActivity, mController);
+        ((ViewGroup) rootView).addView(mGestureController.getView());
+        mGestureController.setListener(this);
+
+        ((ViewGroup) rootView).addView(mController.getView());
         mController.setListener(this);
         mController.setCanReplay(canReplay);
 
+        init(movieActivity, info, canReplay);
+
         mVideoView.setOnErrorListener(this);
         mVideoView.setOnCompletionListener(this);
-        mVideoView.setVideoURI(mUri);
+        mVideoView.setTimerProgress(mTimerController);
+
+        if (mVirtualizer != null) {
+            mVirtualizer.release();
+            mVirtualizer = null;
+        }
 
         Intent ai = movieActivity.getIntent();
         boolean virtualize = ai.getBooleanExtra(VIRTUALIZE_EXTRA, false);
@@ -163,18 +286,6 @@
             }
         });
 
-        // The SurfaceView is transparent before drawing the first frame.
-        // This makes the UI flashing when open a video. (black -> old screen
-        // -> video) However, we have no way to know the timing of the first
-        // frame. So, we hide the VideoView for a while to make sure the
-        // video has been drawn on it.
-        mVideoView.postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                mVideoView.setVisibility(View.VISIBLE);
-            }
-        }, BLACK_TIMEOUT);
-
         setOnSystemUiVisibilityChangeListener();
         // Hide system UI by default
         showSystemUi(false);
@@ -186,20 +297,39 @@
         i.putExtra(CMDNAME, CMDPAUSE);
         movieActivity.sendBroadcast(i);
 
+        // Listen for broadcasts related to user-presence
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(Intent.ACTION_USER_PRESENT);
+        filter.addAction(Intent.ACTION_SHUTDOWN);
+        mContext.registerReceiver(mReceiver, filter);
+
         if (savedInstance != null) { // this is a resumed activity
             mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0);
             mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE);
-            mVideoView.start();
-            mVideoView.suspend();
+            onRestoreInstanceState(savedInstance);
             mHasPaused = true;
+            doStartVideo(true, mVideoPosition, mVideoLastDuration,false);
+            mVideoView.start();
         } else {
-            final Integer bookmark = mBookmarker.getBookmark(mUri);
-            if (bookmark != null) {
-                showResumeDialog(movieActivity, bookmark);
+            mTState = TState.PLAYING;
+            mFirstBePlayed = true;
+            String mUri = mMovieItem.getUri().toString();
+            boolean isLive = mUri.startsWith("rtsp://") && (mUri.contains(".sdp")
+                    || mUri.contains(".smil"));
+            if (!isLive) {
+                final BookmarkerInfo bookmark = mBookmarker.getBookmark(mMovieItem.getUri());
+                if (bookmark != null) {
+                    showResumeDialog(movieActivity, bookmark);
+                } else {
+                    doStartVideo(false, 0, 0);
+                }
             } else {
-                startVideo();
+                doStartVideo(false, 0, 0);
             }
         }
+        mScreenModeExt.setScreenMode();
+        mVideoSnapshotExt.init(mController, mVideoView, isLocalFile());
     }
 
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@@ -213,11 +343,17 @@
                 new View.OnSystemUiVisibilityChangeListener() {
             @Override
             public void onSystemUiVisibilityChange(int visibility) {
+                boolean finish = (mActivityContext == null ? true : mActivityContext.isFinishing());
                 int diff = mLastSystemUiVis ^ visibility;
                 mLastSystemUiVis = visibility;
                 if ((diff & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
                         && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
                     mController.show();
+                    mRootView.setBackgroundColor(Color.BLACK);
+                }
+
+                if (LOG) {
+                    Log.v(TAG, "onSystemUiVisibilityChange(" + visibility + ") finishing()=" + finish);
                 }
             }
         });
@@ -234,7 +370,8 @@
         if (!visible) {
             // We used the deprecated "STATUS_BAR_HIDDEN" for unbundling
             flag |= View.STATUS_BAR_HIDDEN | View.SYSTEM_UI_FLAG_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE;
         }
         mVideoView.setSystemUiVisibility(flag);
     }
@@ -242,14 +379,15 @@
     public void onSaveInstanceState(Bundle outState) {
         outState.putInt(KEY_VIDEO_POSITION, mVideoPosition);
         outState.putLong(KEY_RESUMEABLE_TIME, mResumeableTime);
+        onSaveInstanceStateMore(outState);
     }
 
-    private void showResumeDialog(Context context, final int bookmark) {
+    private void showResumeDialog(Context context, final BookmarkerInfo bookmark) {
         AlertDialog.Builder builder = new AlertDialog.Builder(context);
         builder.setTitle(R.string.resume_playing_title);
         builder.setMessage(String.format(
                 context.getString(R.string.resume_playing_message),
-                GalleryUtils.formatDuration(context, bookmark / 1000)));
+                GalleryUtils.formatDuration(context, bookmark.mBookmark / 1000)));
         builder.setOnCancelListener(new OnCancelListener() {
             @Override
             public void onCancel(DialogInterface dialog) {
@@ -260,40 +398,153 @@
                 R.string.resume_playing_resume, new OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
-                mVideoView.seekTo(bookmark);
-                startVideo();
+                // here try to seek for bookmark
+                mVideoCanSeek = true;
+                doStartVideo(true, bookmark.mBookmark, bookmark.mDuration);
             }
         });
         builder.setNegativeButton(
                 R.string.resume_playing_restart, new OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
-                startVideo();
+                doStartVideo(true, 0, bookmark.mDuration);
             }
         });
-        builder.show();
+        AlertDialog dialog = builder.create();
+        dialog.setOnShowListener(new OnShowListener() {
+            @Override
+            public void onShow(DialogInterface arg0) {
+                mIsShowResumingDialog = true;
+            }
+        });
+        dialog.setOnDismissListener(new OnDismissListener() {
+            @Override
+            public void onDismiss(DialogInterface arg0) {
+                mIsShowResumingDialog = false;
+            }
+        });
+        dialog.show();
     }
 
-    public void onPause() {
+    public void setDefaultScreenMode() {
+        addBackground();
+        mController.setDefaultScreenMode();
+    }
+
+    public boolean onPause() {
+        if (LOG) {
+            Log.v(TAG, "onPause() isLiveStreaming()=" + isLiveStreaming());
+        }
+        boolean pause = false;
+        if (isLiveStreaming()) {
+            pause = false;
+        } else {
+            doOnPause();
+            pause = true;
+        }
+        if (LOG) {
+            Log.v(TAG, "onPause() , return " + pause);
+        }
+        return pause;
+    }
+
+    // we should stop video anyway after this function called.
+    public void onStop() {
+        if (LOG) {
+            Log.v(TAG, "onStop() mHasPaused=" + mHasPaused);
+        }
+        if (!mHasPaused) {
+            doOnPause();
+        }
+    }
+
+    private void doOnPause() {
+        long start = System.currentTimeMillis();
+        addBackground();
         mHasPaused = true;
         mHandler.removeCallbacksAndMessages(null);
-        mVideoPosition = mVideoView.getCurrentPosition();
-        mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration());
+        int position = mVideoView.getCurrentPosition();
+        mVideoPosition = position >= 0 ? position : mVideoPosition;
+        Log.v(TAG, "mVideoPosition is " + mVideoPosition);
+        int duration = mVideoView.getDuration();
+        mVideoLastDuration = duration > 0 ? duration : mVideoLastDuration;
+        mBookmarker.setBookmark(mMovieItem.getUri(), mVideoPosition, mVideoLastDuration);
+        long end1 = System.currentTimeMillis();
         mVideoView.suspend();
         mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT;
+        mVideoView.setResumed(false);// avoid start after surface created
+        long end2 = System.currentTimeMillis();
+        // TODO comments by sunlei
+        mOverlayExt.clearBuffering();
+        mServerTimeoutExt.recordDisconnectTime();
+        if (mGestureController != null) {
+            mGestureController.doOnPause();
+        }
+        if (LOG) {
+            Log.v(TAG, "doOnPause() save video info consume:" + (end1 - start));
+            Log.v(TAG, "doOnPause() suspend video consume:" + (end2 - end1));
+            Log.v(TAG, "doOnPause() mVideoPosition=" + mVideoPosition + ", mResumeableTime="
+                    + mResumeableTime
+                    + ", mVideoLastDuration=" + mVideoLastDuration + ", mIsShowResumingDialog="
+                    + mIsShowResumingDialog);
+        }
     }
 
     public void onResume() {
+        mDragging = false;// clear drag info
         if (mHasPaused) {
-            mVideoView.seekTo(mVideoPosition);
-            mVideoView.resume();
+            if (mServerTimeoutExt.handleOnResume() || mIsShowResumingDialog) {
+                mHasPaused = false;
+                return;
+            }
+            switch (mTState) {
+                case RETRY_ERROR:
+                    mRetryExt.showRetry();
+                    break;
+                case STOPED:
+                    mPlayerExt.stopVideo();
+                    break;
+                case COMPELTED:
+                    mController.showEnded();
+                    if (mVideoCanSeek || mVideoView.canSeekForward()) {
+                        mVideoView.seekTo(mVideoPosition);
+                    }
+                    mVideoView.setDuration(mVideoLastDuration);
+                    break;
+                case PAUSED:
+                    // if video was paused, so it should be started.
+                    doStartVideo(true, mVideoPosition, mVideoLastDuration, false);
+                    pauseVideo();
+                    break;
+                default:
+                    mVideoView.seekTo(mVideoPosition);
+                    mVideoView.resume();
+                    pauseVideoMoreThanThreeMinutes();
+                    break;
+            }
+            mHasPaused = false;
+        }
 
-            // If we have slept for too long, pause the play
-            if (System.currentTimeMillis() > mResumeableTime) {
+        if (System.currentTimeMillis() > mResumeableTime) {
+            mHandler.removeCallbacks(mPlayingChecker);
+            mHandler.postDelayed(mPlayingChecker, 250);
+        }
+
+        mTimerController.startTimer();
+    }
+
+    private void pauseVideoMoreThanThreeMinutes() {
+        // If we have slept for too long, pause the play
+        // If is live streaming, do not pause it too
+        long now = System.currentTimeMillis();
+        if (now > mResumeableTime && !isLiveStreaming()) {
+            if (mVideoCanPause || mVideoView.canPause()) {
                 pauseVideo();
             }
         }
-        mHandler.post(mProgressChecker);
+        if (LOG) {
+            Log.v(TAG, "pauseVideoMoreThanThreeMinutes() now=" + now);
+        }
     }
 
     public void onDestroy() {
@@ -303,27 +554,39 @@
         }
         mVideoView.stopPlayback();
         mAudioBecomingNoisyReceiver.unregister();
+        mContext.unregisterReceiver(mReceiver);
+        mServerTimeoutExt.clearTimeoutDialog();
     }
 
     // This updates the time bar display (if necessary). It is called every
     // second by mProgressChecker and also from places where the time bar needs
     // to be updated immediately.
     private int setProgress() {
-        if (mDragging || !mShowing) {
-            return 0;
-        }
         int position = mVideoView.getCurrentPosition();
         int duration = mVideoView.getDuration();
         mController.setTimes(position, duration, 0, 0);
+
+        if (mDragging || (!mShowing && !mIsOnlyAudio)) {
+            return 0;
+        }
+        if (mControllerRewindAndForwardExt != null
+                && mControllerRewindAndForwardExt.getPlayPauseEanbled()) {
+            updateRewindAndForwardUI();
+        }
         return position;
     }
 
-    private void startVideo() {
+    private void doStartVideo(final boolean enableFasten, final int position, final int duration,
+            boolean start) {
         // For streams that we expect to be slow to start up, show a
         // progress spinner until playback starts.
-        String scheme = mUri.getScheme();
-        if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) {
+        requestAudioFocus();
+        String scheme = mMovieItem.getUri().getScheme();
+        if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)
+                || "https".equalsIgnoreCase(scheme)) {
             mController.showLoading();
+            mController.setLive(isLiveStreaming());
+            mOverlayExt.setPlayingInfo(isLiveStreaming());
             mHandler.removeCallbacks(mPlayingChecker);
             mHandler.postDelayed(mPlayingChecker, 250);
         } else {
@@ -331,35 +594,101 @@
             mController.hide();
         }
 
-        mVideoView.start();
+        if (onIsRTSP()) {
+            Map<String, String> header = new HashMap<String, String>(1);
+            header.put("CODEAURORA-ASYNC-RTSP-PAUSE-PLAY", "true");
+            mVideoView.setVideoURI(mMovieItem.getUri(), header, !mWaitMetaData);
+        } else {
+            mVideoView.setVideoURI(mMovieItem.getUri(), null, !mWaitMetaData);
+        }
+        if (start) {
+            mVideoView.start();
+        }
+        //we may start video from stopVideo,
+        //this case, we should reset canReplay flag according canReplay and loop
+        boolean loop = mPlayerExt.getLoop();
+        boolean canReplay = loop ? loop : mCanReplay;
+        mController.setCanReplay(canReplay);
+        if (position > 0 && (mVideoCanSeek || mVideoView.canSeek())) {
+            mVideoView.seekTo(position);
+        }
+        if (enableFasten) {
+            mVideoView.setDuration(duration);
+        }
         setProgress();
     }
 
-    private void playVideo() {
+    private void doStartVideo(boolean enableFasten, int position, int duration) {
+        doStartVideo(enableFasten, position, duration, true);
+    }
+
+    private boolean playVideo() {
+        if (LOG) {
+            Log.v(TAG, "playVideo()");
+        }
+
+        if (GalleryUtils.isTelephonyCallInProgress(mContext)) {
+            Log.w(TAG, "CS/CSVT Call is in progress, can't play video");
+            return false;
+        }
+        requestAudioFocus();
+        mTState = TState.PLAYING;
         mVideoView.start();
         mController.showPlaying();
         setProgress();
+        return true;
     }
 
     private void pauseVideo() {
+        if (LOG) {
+            Log.v(TAG, "pauseVideo()");
+        }
+        mTState = TState.PAUSED;
         mVideoView.pause();
+        setProgress();
         mController.showPaused();
     }
 
     // Below are notifications from VideoView
     @Override
     public boolean onError(MediaPlayer player, int arg1, int arg2) {
+        mMovieItem.setError();
+        if (mServerTimeoutExt.onError(player, arg1, arg2)) {
+            return true;
+        }
+        if (mRetryExt.onError(player, arg1, arg2)) {
+            return true;
+        }
         mHandler.removeCallbacksAndMessages(null);
         // VideoView will show an error dialog if we return false, so no need
         // to show more message.
+        //M:resume controller
+        mController.setViewEnabled(true);
         mController.showErrorMessage("");
         return false;
     }
 
     @Override
     public void onCompletion(MediaPlayer mp) {
-        mController.showEnded();
-        onCompletion();
+        if (LOG) {
+            Log.v(TAG, "onCompletion() mCanReplay=" + mCanReplay);
+        }
+        if (mMovieItem.getError()) {
+            Log.w(TAG, "error occured, exit the video player!");
+            mHandler.removeCallbacksAndMessages(null);
+            mActivityContext.finish();
+            return;
+        }
+        if (mPlayerExt.getLoop()) {
+            onReplay();
+        } else { //original logic
+            mHandler.removeCallbacksAndMessages(null);
+            mTState = TState.COMPELTED;
+            if (mCanReplay) {
+                mController.showEnded();
+            }
+            onCompletion();
+        }
     }
 
     public void onCompletion() {
@@ -369,9 +698,33 @@
     @Override
     public void onPlayPause() {
         if (mVideoView.isPlaying()) {
-            pauseVideo();
+            onPauseVideo();
         } else {
-            playVideo();
+            onPlayVideo();
+        }
+    }
+
+    private void onPlayVideo() {
+        boolean result = playVideo();
+        if (result) {
+            //set view disabled(play/pause asynchronous processing)
+            mController.setViewEnabled(true);
+            if (mControllerRewindAndForwardExt != null) {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(), false, false);
+            }
+        }
+    }
+
+    private void onPauseVideo() {
+        if (mVideoView != null && mVideoView.canPause()) {
+            pauseVideo();
+            //set view disabled(play/pause asynchronous processing)
+            mController.setViewEnabled(true);
+            if (mControllerRewindAndForwardExt != null) {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(), false, false);
+            }
         }
     }
 
@@ -382,18 +735,27 @@
 
     @Override
     public void onSeekMove(int time) {
-        mVideoView.seekTo(time);
+        if (mVideoView.canSeek()) {
+            mVideoView.seekTo(time);
+        }
     }
 
     @Override
     public void onSeekEnd(int time, int start, int end) {
         mDragging = false;
-        mVideoView.seekTo(time);
+        if (mVideoView.canSeek()) {
+            mVideoView.seekTo(time);
+        }
+    }
+
+    @Override
+    public void onSeekComplete(MediaPlayer mp) {
         setProgress();
     }
 
     @Override
     public void onShown() {
+        addBackground();
         mShowing = true;
         setProgress();
         showSystemUi(true);
@@ -406,8 +768,81 @@
     }
 
     @Override
+    public boolean onInfo(MediaPlayer mp, int what, int extra) {
+        if (LOG) {
+            Log.v(TAG, "onInfo() what:" + what + " extra:" + extra);
+        }
+        if (what == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE && mOverlayExt != null) {
+            boolean flag = (extra == 1);
+            mOverlayExt.setCanPause(flag);
+            mOverlayExt.setCanScrubbing(flag);
+        } else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE && mServerTimeoutExt != null) {
+            Log.e(TAG, "setServerTimeout " + extra);
+            mServerTimeoutExt.setTimeout(extra * 1000);
+        } else if ((what == MediaPlayer.MEDIA_INFO_BUFFERING_START
+                || what == MediaPlayer.MEDIA_INFO_BUFFERING_END) && mOverlayExt != null) {
+            mOverlayExt.showBuffering(what);
+        }
+        if (mRetryExt.onInfo(mp, what, extra)) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onBufferingUpdate(MediaPlayer mp, int percent) {
+    }
+
+    @Override
+    public void onPrepared(MediaPlayer mp) {
+        if (LOG) {
+            Log.v(TAG, "onPrepared(" + mp + ")");
+        }
+        mCoverView.setVisibility(View.GONE);
+        if (!isLocalFile()) {
+            mOverlayExt.setPlayingInfo(isLiveStreaming());
+        }
+        getVideoInfo(mp);
+        boolean canPause = mVideoView.canPause();
+        boolean canSeek = mVideoView.canSeek();
+        mOverlayExt.setCanPause(canPause);
+        mOverlayExt.setCanScrubbing(canSeek);
+        mController.setPlayPauseReplayResume();
+        if (!canPause && !mVideoView.isTargetPlaying()) {
+            requestAudioFocus();
+            mVideoView.start();
+        }
+        updateRewindAndForwardUI();
+        if (LOG) {
+            Log.v(TAG, "onPrepared() canPause=" + canPause + ", canSeek=" + canSeek);
+        }
+    }
+
+    public boolean onIsRTSP() {
+        if (MovieUtils.isRtspStreaming(mMovieItem.getUri(), mMovieItem
+                .getMimeType())) {
+            if (LOG) {
+                Log.v(TAG, "onIsRTSP() is RTSP");
+            }
+            return true;
+        }
+        if (LOG) {
+            Log.v(TAG, "onIsRTSP() is not RTSP");
+        }
+        return false;
+    }
+
+    @Override
     public void onReplay() {
-        startVideo();
+        if (LOG) {
+            Log.v(TAG, "onReplay()");
+        }
+        mTState = TState.PLAYING;
+        mFirstBePlayed = true;
+        if (mRetryExt.handleOnReplay()) {
+            return;
+        }
+        doStartVideo(false, 0, 0);
     }
 
     // Below are key events passed from MovieActivity.
@@ -421,14 +856,14 @@
         switch (keyCode) {
             case KeyEvent.KEYCODE_HEADSETHOOK:
             case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-                if (mVideoView.isPlaying()) {
+                if (mVideoView.isPlaying() && mVideoView.canPause()) {
                     pauseVideo();
                 } else {
                     playVideo();
                 }
                 return true;
             case KEYCODE_MEDIA_PAUSE:
-                if (mVideoView.isPlaying()) {
+                if (mVideoView.isPlaying() && mVideoView.canPause()) {
                     pauseVideo();
                 }
                 return true;
@@ -450,6 +885,21 @@
         return isMediaKey(keyCode);
     }
 
+    public void updateRewindAndForwardUI() {
+        if (LOG) {
+            Log.v(TAG, "updateRewindAndForwardUI: " +
+                    "getCurrentPosition = " + mVideoView.getCurrentPosition() + ", " +
+                    "getDuration = " + mVideoView.getDuration());
+        }
+        if (mControllerRewindAndForwardExt != null) {
+            mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                    .canStop(), mVideoView.canSeekBackward()
+                    && mControllerRewindAndForwardExt.getTimeBarEanbled(), mVideoView
+                    .canSeekForward()
+                    && mControllerRewindAndForwardExt.getTimeBarEanbled());
+        }
+    }
+
     private static boolean isMediaKey(int keyCode) {
         return keyCode == KeyEvent.KEYCODE_HEADSETHOOK
                 || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS
@@ -459,6 +909,30 @@
                 || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE;
     }
 
+    private void init(MovieActivity movieActivity, IMovieItem info, boolean canReplay) {
+        mActivityContext = movieActivity;
+        mCanReplay = canReplay;
+        mMovieItem = info;
+        judgeStreamingType(info.getUri(), info.getMimeType());
+
+        mVideoView.setOnInfoListener(this);
+        mVideoView.setOnPreparedListener(this);
+        mVideoView.setOnBufferingUpdateListener(this);
+        mVideoView.setOnVideoSizeChangedListener(this);
+        mRootView.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                mController.show();
+                return true;
+            }
+        });
+        mOverlayExt = mController.getOverlayExt();
+        mControllerRewindAndForwardExt = mController.getControllerRewindAndForwardExt();
+        if (mControllerRewindAndForwardExt != null) {
+            mControllerRewindAndForwardExt.setIListener(mRewindAndForwardListener);
+        }
+    }
+
     // We want to pause when the headset is unplugged.
     private class AudioBecomingNoisyReceiver extends BroadcastReceiver {
 
@@ -473,9 +947,712 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (mVideoView.isPlaying()) pauseVideo();
+            if (mVideoView.isPlaying() && mVideoView.canPause()) pauseVideo();
         }
     }
+
+    public int getAudioSessionId() {
+        return mVideoView.getAudioSessionId();
+    }
+
+    public void setOnPreparedListener(MediaPlayer.OnPreparedListener listener) {
+        mVideoView.setOnPreparedListener(listener);
+    }
+
+    public boolean isFullBuffer() {
+        if (mStreamingType == STREAMING_RTSP || mStreamingType == STREAMING_SDP
+                || mStreamingType == STREAMING_HTTP) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean isLocalFile() {
+        if (mStreamingType == STREAMING_LOCAL) {
+            return true;
+        }
+        return false;
+    }
+
+    private void getVideoInfo(MediaPlayer mp) {
+        if (!MovieUtils.isLocalFile(mMovieItem.getUri(), mMovieItem.getMimeType())) {
+            ApiHelper.Metadata data = ApiHelper.MediaPlayer.getMetadata(mp,
+                    ApiHelper.MediaPlayer.METADATA_ALL,
+                    ApiHelper.MediaPlayer.BYPASS_METADATA_FILTER);
+            if (data != null) {
+                mServerTimeoutExt.setVideoInfo(data);
+            } else {
+                Log.w(TAG, "Metadata is null!");
+            }
+        }
+    }
+
+    private void judgeStreamingType(Uri uri, String mimeType) {
+        if (LOG) {
+            Log.v(TAG, "judgeStreamingType(" + uri + ")");
+        }
+        if (uri == null) {
+            return;
+        }
+        String scheme = uri.getScheme();
+        mWaitMetaData = true;
+        if (MovieUtils.isSdpStreaming(uri, mimeType)) {
+            mStreamingType = STREAMING_SDP;
+            mWaitMetaData = false;
+        } else if (MovieUtils.isRtspStreaming(uri, mimeType)) {
+            mStreamingType = STREAMING_RTSP;
+            mWaitMetaData = false;
+        } else if (MovieUtils.isHttpStreaming(uri, mimeType)) {
+            mStreamingType = STREAMING_HTTP;
+            mWaitMetaData = false;
+        } else {
+            mStreamingType = STREAMING_LOCAL;
+            mWaitMetaData = false;
+        }
+        if (LOG) {
+            Log.v(TAG, "mStreamingType=" + mStreamingType
+                    + " mCanGetMetaData=" + mWaitMetaData);
+        }
+    }
+
+    public boolean isLiveStreaming() {
+        boolean isLive = false;
+        if (mStreamingType == STREAMING_SDP) {
+            isLive = true;
+        }
+        if (LOG) {
+            Log.v(TAG, "isLiveStreaming() return " + isLive);
+        }
+        return isLive;
+    }
+
+    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
+        // reget the audio type
+        if (width != 0 && height != 0) {
+            mIsOnlyAudio = false;
+        } else {
+            mIsOnlyAudio = true;
+        }
+        mOverlayExt.setBottomPanel(mIsOnlyAudio, true);
+        if (LOG) {
+            Log.v(TAG, "onVideoSizeChanged(" + width + ", " + height + ") mIsOnlyAudio="
+                    + mIsOnlyAudio);
+        }
+    }
+
+    public IMoviePlayer getMoviePlayerExt() {
+        return mPlayerExt;
+    }
+
+    public SurfaceView getVideoSurface() {
+        return mVideoView;
+    }
+
+    // add background for removing ghost image.
+    private void addBackground() {
+        if (LOG) {
+            Log.v(TAG, "addBackground()");
+        }
+        mRootView.setBackgroundColor(Color.BLACK);
+    }
+
+    private void clearVideoInfo() {
+        mVideoPosition = 0;
+        mVideoLastDuration = 0;
+        mIsOnlyAudio = false;
+
+        if (mServerTimeoutExt != null) {
+            mServerTimeoutExt.clearServerInfo();
+        }
+    }
+
+    private void onSaveInstanceStateMore(Bundle outState) {
+        outState.putInt(KEY_VIDEO_LAST_DURATION, mVideoLastDuration);
+        outState.putBoolean(KEY_VIDEO_CAN_SEEK, mVideoView.canSeekForward());
+        outState.putBoolean(KEY_VIDEO_CAN_PAUSE, mVideoView.canPause());
+        outState.putInt(KEY_VIDEO_STREAMING_TYPE, mStreamingType);
+        outState.putString(KEY_VIDEO_STATE, String.valueOf(mTState));
+        mServerTimeoutExt.onSaveInstanceState(outState);
+        mScreenModeExt.onSaveInstanceState(outState);
+        mRetryExt.onSaveInstanceState(outState);
+        mPlayerExt.onSaveInstanceState(outState);
+    }
+
+    private void onRestoreInstanceState(Bundle icicle) {
+        mVideoLastDuration = icicle.getInt(KEY_VIDEO_LAST_DURATION);
+        mVideoCanSeek = icicle.getBoolean(KEY_VIDEO_CAN_SEEK);
+        mVideoCanPause = icicle.getBoolean(KEY_VIDEO_CAN_PAUSE);
+        mStreamingType = icicle.getInt(KEY_VIDEO_STREAMING_TYPE);
+        mTState = TState.valueOf(icicle.getString(KEY_VIDEO_STATE));
+        mServerTimeoutExt.onRestoreInstanceState(icicle);
+        mScreenModeExt.onRestoreInstanceState(icicle);
+        mRetryExt.onRestoreInstanceState(icicle);
+        mPlayerExt.onRestoreInstanceState(icicle);
+    }
+
+    private class MoviePlayerExtension implements IMoviePlayer, Restorable {
+
+        private static final String KEY_VIDEO_IS_LOOP = "video_is_loop";
+
+        private BookmarkEnhance mBookmark;//for bookmark
+        private boolean mIsLoop;
+        private boolean mLastPlaying;
+        private boolean mLastCanPaused;
+
+        @Override
+        public boolean getLoop() {
+            return mIsLoop;
+        }
+
+        @Override
+        public void setLoop(boolean loop) {
+            if (isLocalFile()) {
+                mIsLoop = loop;
+                mController.setCanReplay(loop);
+            }
+        }
+
+        @Override
+        public void startNextVideo(IMovieItem item) {
+            IMovieItem next = item;
+            if (next != null && next != mMovieItem) {
+                int position = mVideoView.getCurrentPosition();
+                int duration = mVideoView.getDuration();
+                mBookmarker.setBookmark(mMovieItem.getUri(), position, duration);
+                mVideoView.stopPlayback();
+                mVideoView.setVisibility(View.INVISIBLE);
+                clearVideoInfo();
+                mMovieItem = next;
+                mActivityContext.refreshMovieInfo(mMovieItem);
+                doStartVideo(false, 0, 0);
+                mVideoView.setVisibility(View.VISIBLE);
+            } else {
+                Log.e(TAG, "Cannot play the next video! " + item);
+            }
+            mActivityContext.closeOptionsMenu();
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle icicle) {
+            mIsLoop = icicle.getBoolean(KEY_VIDEO_IS_LOOP, false);
+            if (mIsLoop) {
+                mController.setCanReplay(true);
+            } // else  will get can replay from intent.
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            outState.putBoolean(KEY_VIDEO_IS_LOOP, mIsLoop);
+        }
+
+        @Override
+        public void stopVideo() {
+            if (LOG) {
+                Log.v(TAG, "stopVideo()");
+            }
+            mTState = TState.STOPED;
+            mVideoView.clearSeek();
+            mVideoView.clearDuration();
+            mVideoView.stopPlayback();
+            mVideoView.setResumed(false);
+            mVideoView.setVisibility(View.INVISIBLE);
+            clearVideoInfo();
+            mFirstBePlayed = false;
+            mController.setCanReplay(true);
+            mController.showEnded();
+            mController.setViewEnabled(true);
+            setProgress();
+        }
+
+        @Override
+        public boolean canStop() {
+            boolean stopped = false;
+            if (mController != null) {
+                stopped = mOverlayExt.isPlayingEnd();
+            }
+            if (LOG) {
+                Log.v(TAG, "canStop() stopped=" + stopped);
+            }
+            return !stopped;
+        }
+
+        @Override
+        public void addBookmark() {
+            if (mBookmark == null) {
+                mBookmark = new BookmarkEnhance(mActivityContext);
+            }
+            String uri = String.valueOf(mMovieItem.getUri());
+            if (mBookmark.exists(uri)) {
+                Toast.makeText(mActivityContext, R.string.bookmark_exist, Toast.LENGTH_SHORT)
+                        .show();
+            } else {
+                mBookmark.insert(mMovieItem.getTitle(), uri,
+                        mMovieItem.getMimeType(), 0);
+                Toast.makeText(mActivityContext, R.string.bookmark_add_success, Toast.LENGTH_SHORT)
+                        .show();
+            }
+        }
+    };
+
+    private class RetryExtension implements Restorable, MediaPlayer.OnErrorListener,
+            MediaPlayer.OnInfoListener {
+        private static final String KEY_VIDEO_RETRY_COUNT = "video_retry_count";
+        private int mRetryDuration;
+        private int mRetryPosition;
+        private int mRetryCount;
+
+        public void retry() {
+            doStartVideo(true, mRetryPosition, mRetryDuration);
+            if (LOG) {
+                Log.v(TAG, "retry() mRetryCount=" + mRetryCount + ", mRetryPosition="
+                        + mRetryPosition);
+            }
+        }
+
+        public void clearRetry() {
+            if (LOG) {
+                Log.v(TAG, "clearRetry() mRetryCount=" + mRetryCount);
+            }
+            mRetryCount = 0;
+        }
+
+        public boolean reachRetryCount() {
+            if (LOG) {
+                Log.v(TAG, "reachRetryCount() mRetryCount=" + mRetryCount);
+            }
+            if (mRetryCount > 3) {
+                return true;
+            }
+            return false;
+        }
+
+        public int getRetryCount() {
+            if (LOG) {
+                Log.v(TAG, "getRetryCount() return " + mRetryCount);
+            }
+            return mRetryCount;
+        }
+
+        public boolean isRetrying() {
+            boolean retry = false;
+            if (mRetryCount > 0) {
+                retry = true;
+            }
+            if (LOG) {
+                Log.v(TAG, "isRetrying() mRetryCount=" + mRetryCount);
+            }
+            return retry;
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle icicle) {
+            mRetryCount = icicle.getInt(KEY_VIDEO_RETRY_COUNT);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            outState.putInt(KEY_VIDEO_RETRY_COUNT, mRetryCount);
+        }
+
+        @Override
+        public boolean onError(MediaPlayer mp, int what, int extra) {
+            return false;
+        }
+
+        @Override
+        public boolean onInfo(MediaPlayer mp, int what, int extra) {
+            return false;
+        }
+
+        public boolean handleOnReplay() {
+            if (isRetrying()) { // from connecting error
+                clearRetry();
+                int errorPosition = mVideoView.getCurrentPosition();
+                int errorDuration = mVideoView.getDuration();
+                doStartVideo(errorPosition > 0, errorPosition, errorDuration);
+                if (LOG) {
+                    Log.v(TAG, "onReplay() errorPosition=" + errorPosition + ", errorDuration="
+                            + errorDuration);
+                }
+                return true;
+            }
+            return false;
+        }
+
+        public void showRetry() {
+            if (mVideoCanSeek || mVideoView.canSeekForward()) {
+                mVideoView.seekTo(mVideoPosition);
+            }
+            mVideoView.setDuration(mVideoLastDuration);
+            mRetryPosition = mVideoPosition;
+            mRetryDuration = mVideoLastDuration;
+        }
+    }
+    private class ServerTimeoutExtension implements Restorable, MediaPlayer.OnErrorListener {
+        // for cmcc server timeout case
+        // please remember to clear this value when changed video.
+        private int mServerTimeout = -1;
+        private long mLastDisconnectTime;
+        private boolean mIsShowDialog = false;
+        private AlertDialog mServerTimeoutDialog;
+        private int RESUME_DIALOG_TIMEOUT = 3 * 60 * 1000; // 3 mins
+
+        // check whether disconnect from server timeout or not.
+        // if timeout, return false. otherwise, return true.
+        private boolean passDisconnectCheck() {
+            if (!isFullBuffer()) {
+                // record the time disconnect from server
+                long now = System.currentTimeMillis();
+                if (LOG) {
+                    Log.v(TAG, "passDisconnectCheck() now=" + now + ", mLastDisconnectTime="
+                            + mLastDisconnectTime
+                            + ", mServerTimeout=" + mServerTimeout);
+                }
+                if (mServerTimeout > 0 && (now - mLastDisconnectTime) > mServerTimeout) {
+                    // disconnect time more than server timeout, notify user
+                    notifyServerTimeout();
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private void recordDisconnectTime() {
+            if (!isFullBuffer()) {
+                // record the time disconnect from server
+                mLastDisconnectTime = System.currentTimeMillis();
+            }
+            if (LOG) {
+                Log.v(TAG, "recordDisconnectTime() mLastDisconnectTime=" + mLastDisconnectTime);
+            }
+        }
+
+        private void clearServerInfo() {
+            mServerTimeout = -1;
+        }
+
+        private void notifyServerTimeout() {
+            if (mServerTimeoutDialog == null) {
+                // for updating last position and duration.
+                if (mVideoCanSeek || mVideoView.canSeekForward()) {
+                    mVideoView.seekTo(mVideoPosition);
+                }
+                mVideoView.setDuration(mVideoLastDuration);
+                AlertDialog.Builder builder = new AlertDialog.Builder(mActivityContext);
+                mServerTimeoutDialog = builder.setTitle(R.string.server_timeout_title)
+                        .setMessage(R.string.server_timeout_message)
+                        .setNegativeButton(android.R.string.cancel, new OnClickListener() {
+
+                            public void onClick(DialogInterface dialog, int which) {
+                                if (LOG) {
+                                    Log.v(TAG, "NegativeButton.onClick() mIsShowDialog="
+                                            + mIsShowDialog);
+                                }
+                                mController.showEnded();
+                                onCompletion();
+                            }
+
+                        })
+                        .setPositiveButton(R.string.resume_playing_resume, new OnClickListener() {
+
+                            public void onClick(DialogInterface dialog, int which) {
+                                if (LOG) {
+                                    Log.v(TAG, "PositiveButton.onClick() mIsShowDialog="
+                                            + mIsShowDialog);
+                                }
+                                mVideoView.setDialogShowState(false);
+                                doStartVideo(true, mVideoPosition, mVideoLastDuration);
+                            }
+
+                        })
+                        .setOnCancelListener(new OnCancelListener() {
+                            public void onCancel(DialogInterface dialog) {
+                                mController.showEnded();
+                                onCompletion();
+                            }
+                        })
+                        .create();
+                mServerTimeoutDialog.setOnDismissListener(new OnDismissListener() {
+
+                    public void onDismiss(DialogInterface dialog) {
+                        if (LOG) {
+                            Log.v(TAG, "mServerTimeoutDialog.onDismiss()");
+                        }
+                        mVideoView.setDialogShowState(false);
+                        mIsShowDialog = false;
+                    }
+
+                });
+                mServerTimeoutDialog.setOnShowListener(new OnShowListener() {
+
+                    public void onShow(DialogInterface dialog) {
+                        if (LOG) {
+                            Log.v(TAG, "mServerTimeoutDialog.onShow()");
+                        }
+                        mVideoView.setDialogShowState(true);
+                        mIsShowDialog = true;
+                    }
+
+                });
+            }
+            mServerTimeoutDialog.show();
+        }
+
+        private void clearTimeoutDialog() {
+            if (mServerTimeoutDialog != null && mServerTimeoutDialog.isShowing()) {
+                mServerTimeoutDialog.dismiss();
+            }
+            mServerTimeoutDialog = null;
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle icicle) {
+            mLastDisconnectTime = icicle.getLong(KEY_VIDEO_LAST_DISCONNECT_TIME);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            outState.putLong(KEY_VIDEO_LAST_DISCONNECT_TIME, mLastDisconnectTime);
+        }
+
+        public boolean handleOnResume() {
+            if (mIsShowDialog && !isLiveStreaming()) {
+                // wait for user's operation
+                return true;
+            }
+            if (!passDisconnectCheck()) {
+                return true;
+            }
+            return false;
+        }
+
+        public void setVideoInfo(ApiHelper.Metadata data) {
+            mServerTimeout = RESUME_DIALOG_TIMEOUT;
+            if (data.has(SERVER_TIMEOUT)) {
+                mServerTimeout = data.getInt(SERVER_TIMEOUT);
+                if (mServerTimeout == 0) {
+                    mServerTimeout = RESUME_DIALOG_TIMEOUT;
+                }
+                if (LOG) {
+                    Log.v(TAG, "get server timeout from metadata. mServerTimeout="
+                            + mServerTimeout);
+                }
+            }
+        }
+
+        @Override
+        public boolean onError(MediaPlayer mp, int what, int extra) {
+            // if we are showing a dialog, cancel the error dialog
+            if (mIsShowDialog) {
+                return true;
+            }
+            return false;
+        }
+
+        public void setTimeout(int timeout) {
+            mServerTimeout = timeout;
+        }
+    }
+
+    private class ScreenModeExt implements Restorable, ScreenModeListener {
+        private static final String KEY_VIDEO_SCREEN_MODE = "video_screen_mode";
+        private int mScreenMode = ScreenModeManager.SCREENMODE_BIGSCREEN;
+        private ScreenModeManager mScreenModeManager = new ScreenModeManager();
+
+        public void setScreenMode() {
+            mVideoView.setScreenModeManager(mScreenModeManager);
+            mController.setScreenModeManager(mScreenModeManager);
+            mScreenModeManager.addListener(this);
+            //notify all listener to change screen mode
+            mScreenModeManager.setScreenMode(mScreenMode);
+            if (LOG) {
+                Log.v(TAG, "setScreenMode() mScreenMode=" + mScreenMode);
+            }
+        }
+
+        @Override
+        public void onScreenModeChanged(int newMode) {
+            mScreenMode = newMode;// changed from controller
+            if (LOG) {
+                Log.v(TAG, "OnScreenModeClicked(" + newMode + ")");
+            }
+        }
+
+        @Override
+        public void onRestoreInstanceState(Bundle icicle) {
+            mScreenMode = icicle.getInt(KEY_VIDEO_SCREEN_MODE,
+                    ScreenModeManager.SCREENMODE_BIGSCREEN);
+        }
+
+        @Override
+        public void onSaveInstanceState(Bundle outState) {
+            outState.putInt(KEY_VIDEO_SCREEN_MODE, mScreenMode);
+        }
+    }
+
+    private class ControllerRewindAndForwardExt implements IRewindAndForwardListener {
+        @Override
+        public void onPlayPause() {
+            onPlayPause();
+        }
+
+        @Override
+        public void onSeekStart() {
+            onSeekStart();
+        }
+
+        @Override
+        public void onSeekMove(int time) {
+            onSeekMove(time);
+        }
+
+        @Override
+        public void onSeekEnd(int time, int trimStartTime, int trimEndTime) {
+            onSeekEnd(time, trimStartTime, trimEndTime);
+        }
+
+        @Override
+        public void onShown() {
+            onShown();
+        }
+
+        @Override
+        public void onHidden() {
+            onHidden();
+        }
+
+        @Override
+        public void onReplay() {
+            onReplay();
+        }
+
+        @Override
+        public boolean onIsRTSP() {
+            return false;
+        }
+
+        @Override
+        public void onStopVideo() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onStopVideo()");
+            }
+            if (mPlayerExt.canStop()) {
+                mPlayerExt.stopVideo();
+                mControllerRewindAndForwardExt.showControllerButtonsView(false,
+                        false, false);
+            }
+        }
+
+        @Override
+        public void onRewind() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onRewind()");
+            }
+            if (mVideoView != null && mVideoView.canSeekBackward()) {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(),
+                        false, false);
+                int stepValue = getStepOptionValue();
+                int targetDuration = mVideoView.getCurrentPosition()
+                        - stepValue < 0 ? 0 : mVideoView.getCurrentPosition()
+                        - stepValue;
+                if (LOG) {
+                    Log.v(TAG, "onRewind targetDuration " + targetDuration);
+                }
+                mVideoView.seekTo(targetDuration);
+            } else {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(),
+                        false, false);
+            }
+        }
+
+        @Override
+        public void onForward() {
+            if (LOG) {
+                Log.v(TAG, "ControllerRewindAndForwardExt onForward()");
+            }
+            if (mVideoView != null && mVideoView.canSeekForward()) {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(),
+                        false, false);
+                int stepValue = getStepOptionValue();
+                int targetDuration = mVideoView.getCurrentPosition()
+                        + stepValue > mVideoView.getDuration() ? mVideoView
+                        .getDuration() : mVideoView.getCurrentPosition()
+                        + stepValue;
+                if (LOG) {
+                    Log.v(TAG, "onForward targetDuration " + targetDuration);
+                }
+                mVideoView.seekTo(targetDuration);
+            } else {
+                mControllerRewindAndForwardExt.showControllerButtonsView(mPlayerExt
+                        .canStop(),
+                        false, false);
+            }
+        }
+    }
+
+    public int getStepOptionValue() {
+        final String slectedStepOption = "selected_step_option";
+        final String videoPlayerData = "video_player_data";
+        final int stepBase = 3000;
+        final int stepOptionThreeSeconds = 0;
+        SharedPreferences mPrefs = mContext.getSharedPreferences(
+                videoPlayerData, 0);
+        return (mPrefs.getInt(slectedStepOption, stepOptionThreeSeconds) + 1) * stepBase;
+    }
+
+    public void restartHidingController() {
+        if (mController != null) {
+            mController.maybeStartHiding();
+        }
+    }
+
+    public void cancelHidingController() {
+        if (mController != null) {
+            mController.cancelHiding();
+        }
+    }
+
+    private AudioManager.OnAudioFocusChangeListener mAudioFocusChangeListener =
+            new AudioManager.OnAudioFocusChangeListener() {
+                @Override
+                public void onAudioFocusChange(int focusChange) {
+                    switch (focusChange) {
+                        case AudioManager.AUDIOFOCUS_GAIN:
+                            boolean isTargetPlaying = (mVideoView != null &&
+                                    mVideoView.isTargetPlaying());
+                            Log.d(TAG, "AUDIOFOCUS_GAIN isTargetPlaying : " + isTargetPlaying);
+                            if (mPausedByTransientLossOfFocus || isTargetPlaying) {
+                                onPlayVideo();
+                                mPausedByTransientLossOfFocus = false;
+                            }
+                            break;
+                        case AudioManager.AUDIOFOCUS_LOSS:
+                        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+                            boolean isPlaying = (mVideoView != null && mVideoView.isPlaying());
+                            Log.d(TAG, "AUDIOFOCUS_LOSS isPlaying : " + isPlaying);
+                            if (isPlaying) {
+                                onPauseVideo();
+                                mPausedByTransientLossOfFocus = true;
+                            }
+                            break;
+                        default:
+                    }
+                }
+    };
+
+    public int requestAudioFocus() {
+        AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        return am.requestAudioFocus(mAudioFocusChangeListener, AudioManager.STREAM_MUSIC,
+                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+    }
+
+    public int abandonAudioFocus() {
+        AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        return am.abandonAudioFocus(mAudioFocusChangeListener);
+    }
 }
 
 class Bookmarker {
@@ -497,6 +1674,10 @@
 
     public void setBookmark(Uri uri, int bookmark, int duration) {
         try {
+            // do not record or override bookmark if duration is not valid.
+            if (duration <= 0) {
+                return;
+            }
             BlobCache cache = CacheManager.getCache(mContext,
                     BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
                     BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION);
@@ -505,7 +1686,7 @@
             DataOutputStream dos = new DataOutputStream(bos);
             dos.writeUTF(uri.toString());
             dos.writeInt(bookmark);
-            dos.writeInt(duration);
+            dos.writeInt(Math.abs(duration));
             dos.flush();
             cache.insert(uri.hashCode(), bos.toByteArray());
         } catch (Throwable t) {
@@ -513,11 +1694,12 @@
         }
     }
 
-    public Integer getBookmark(Uri uri) {
+    public BookmarkerInfo getBookmark(Uri uri) {
         try {
             BlobCache cache = CacheManager.getCache(mContext,
                     BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES,
                     BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION);
+            if (cache == null) return null;
 
             byte[] data = cache.lookup(uri.hashCode());
             if (data == null) return null;
@@ -537,10 +1719,31 @@
                     || (bookmark > (duration - HALF_MINUTE))) {
                 return null;
             }
-            return Integer.valueOf(bookmark);
+            return new BookmarkerInfo(bookmark, duration);
         } catch (Throwable t) {
             Log.w(TAG, "getBookmark failed", t);
         }
         return null;
     }
 }
+
+class BookmarkerInfo {
+    public final int mBookmark;
+    public final int mDuration;
+
+    public BookmarkerInfo(int bookmark, int duration) {
+        this.mBookmark = bookmark;
+        this.mDuration = duration;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append("BookmarkInfo(bookmark=")
+                .append(mBookmark)
+                .append(", duration=")
+                .append(mDuration)
+                .append(")")
+                .toString();
+    }
+}
diff --git a/src/com/android/gallery3d/app/MuteVideo.java b/src/com/android/gallery3d/app/MuteVideo.java
old mode 100644
new mode 100755
index d3f3aa5..7f50c9c
--- a/src/com/android/gallery3d/app/MuteVideo.java
+++ b/src/com/android/gallery3d/app/MuteVideo.java
@@ -16,6 +16,8 @@
 
 package com.android.gallery3d.app;
 
+import java.util.ArrayList;
+
 import android.app.Activity;
 import android.app.ProgressDialog;
 import android.content.Intent;
@@ -24,10 +26,11 @@
 import android.provider.MediaStore;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.util.SaveVideoFileInfo;
 import com.android.gallery3d.util.SaveVideoFileUtils;
+import androidx.core.content.FileProvider;
 
 import java.io.IOException;
 
@@ -40,6 +43,13 @@
     private SaveVideoFileInfo mDstFileInfo = null;
     private Activity mActivity = null;
     private final Handler mHandler = new Handler();
+    private String mMimeType;
+    ArrayList<String> mUnsupportedMuteFileTypes = new ArrayList<String>();
+    private final String FILE_TYPE_DIVX = "video/divx";
+    private final String FILE_TYPE_AVI = "video/avi";
+    private final String FILE_TYPE_WMV = "video/x-ms-wmv";
+    private final String FILE_TYPE_ASF = "video/x-ms-asf";
+    private final String FILE_TYPE_WEBM = "video/webm";
 
     final String TIME_STAMP_NAME = "'MUTE'_yyyyMMdd_HHmmss";
 
@@ -47,6 +57,13 @@
         mUri = uri;
         mFilePath = filePath;
         mActivity = activity;
+        if (mUnsupportedMuteFileTypes != null) {
+            mUnsupportedMuteFileTypes.add(FILE_TYPE_DIVX);
+            mUnsupportedMuteFileTypes.add(FILE_TYPE_AVI);
+            mUnsupportedMuteFileTypes.add(FILE_TYPE_WMV);
+            mUnsupportedMuteFileTypes.add(FILE_TYPE_ASF);
+            mUnsupportedMuteFileTypes.add(FILE_TYPE_WEBM);
+        }
     }
 
     public void muteInBackground() {
@@ -54,6 +71,15 @@
                 mActivity.getContentResolver(), mUri,
                 mActivity.getString(R.string.folder_download));
 
+        mMimeType = mActivity.getContentResolver().getType(mUri);
+        if(!isValidFileForMute(mMimeType)) {
+            Toast.makeText(mActivity.getApplicationContext(),
+                           mActivity.getString(R.string.mute_nosupport),
+                           Toast.LENGTH_SHORT)
+                           .show();
+            return;
+        }
+
         showProgressDialog();
         new Thread(new Runnable() {
                 @Override
@@ -62,9 +88,21 @@
                     VideoUtils.startMute(mFilePath, mDstFileInfo);
                     SaveVideoFileUtils.insertContent(
                             mDstFileInfo, mActivity.getContentResolver(), mUri);
-                } catch (IOException e) {
-                    Toast.makeText(mActivity, mActivity.getString(R.string.video_mute_err),
-                            Toast.LENGTH_SHORT).show();
+                } catch (Exception e) {
+                    mHandler.post(new Runnable() {
+                    @Override
+                        public void run() {
+                            Toast.makeText(mActivity, mActivity.getString(R.string.video_mute_err),
+                                Toast.LENGTH_SHORT).show();
+                            if (mMuteProgress != null) {
+                                if (isActivityValid(mActivity)) {
+                                    mMuteProgress.dismiss();
+                                }
+                                mMuteProgress = null;
+                            }
+                        }
+                    });
+                    return;
                 }
                 // After muting is done, trigger the UI changed.
                 mHandler.post(new Runnable() {
@@ -77,14 +115,20 @@
                                 .show();
 
                         if (mMuteProgress != null) {
-                            mMuteProgress.dismiss();
+                            if (isActivityValid(mActivity)) {
+                                mMuteProgress.dismiss();
+                            }
                             mMuteProgress = null;
 
                             // Show the result only when the activity not
                             // stopped.
                             Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
-                            intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*");
+                            intent.setDataAndType(
+                                    FileProvider.getUriForFile(mActivity,
+                                            "com.android.gallery3d.fileprovider",
+                                            mDstFileInfo.mFile), "video/*");
                             intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false);
+                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                             mActivity.startActivity(intent);
                         }
                     }
@@ -99,6 +143,24 @@
         mMuteProgress.setMessage(mActivity.getString(R.string.please_wait));
         mMuteProgress.setCancelable(false);
         mMuteProgress.setCanceledOnTouchOutside(false);
-        mMuteProgress.show();
+        if (isActivityValid(mActivity)) {
+            mMuteProgress.show();
+        }
+    }
+    private boolean isValidFileForMute(String mimeType) {
+        if (mimeType != null) {
+            for (String fileType : mUnsupportedMuteFileTypes) {
+               if (mimeType.equals(fileType)) {
+                   return false;
+               }
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isActivityValid(Activity activity) {
+        return (!activity.isDestroyed() && !activity.isFinishing());
     }
 }
diff --git a/src/com/android/gallery3d/app/PackagesMonitor.java b/src/com/android/gallery3d/app/PackagesMonitor.java
deleted file mode 100644
index be262fd..0000000
--- a/src/com/android/gallery3d/app/PackagesMonitor.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gallery3d.app;
-
-import android.app.IntentService;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import androidx.core.app.JobIntentService;
-
-import com.android.gallery3d.picasasource.PicasaSource;
-import com.android.gallery3d.util.LightCycleHelper;
-
-public class PackagesMonitor extends BroadcastReceiver {
-    public static final String KEY_PACKAGES_VERSION  = "packages-version";
-
-    public synchronized static int getPackagesVersion(Context context) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-        return prefs.getInt(KEY_PACKAGES_VERSION, 1);
-    }
-
-    @Override
-    public void onReceive(final Context context, final Intent intent) {
-        intent.setClass(context, AsyncService.class);
-        AsyncService.enqueueWork(context, intent);
-    }
-
-    public static class AsyncService extends JobIntentService {
-        public static final int JOB_ID = 1;
-
-        public static void enqueueWork(Context context, Intent work) {
-            enqueueWork(context, AsyncService.class, JOB_ID, work);
-        }
-
-        @Override
-        protected void onHandleWork(Intent intent) {
-            onReceiveAsync(this, intent);
-        }
-    }
-
-    // Runs in a background thread.
-    private static void onReceiveAsync(Context context, Intent intent) {
-        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-
-        int version = prefs.getInt(KEY_PACKAGES_VERSION, 1);
-        prefs.edit().putInt(KEY_PACKAGES_VERSION, version + 1).commit();
-
-        String action = intent.getAction();
-        String packageName = intent.getData().getSchemeSpecificPart();
-        if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-            PicasaSource.onPackageAdded(context, packageName);
-        } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-            PicasaSource.onPackageRemoved(context, packageName);
-        } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-            PicasaSource.onPackageChanged(context, packageName);
-        }
-    }
-}
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java
old mode 100644
new mode 100755
index fd3a7cf..baece70
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java
@@ -20,16 +20,21 @@
 import android.graphics.BitmapRegionDecoder;
 import android.os.Handler;
 import android.os.Message;
+import android.text.TextUtils;
+import android.view.View;
 
 import com.android.gallery3d.common.BitmapUtils;
 import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.CameraShortcutImage;
 import com.android.gallery3d.data.ContentListener;
 import com.android.gallery3d.data.LocalMediaItem;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaSet;
 import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.SnailItem;
 import com.android.gallery3d.glrenderer.TiledTexture;
+import com.android.gallery3d.ui.BitmapScreenNail;
 import com.android.gallery3d.ui.PhotoView;
 import com.android.gallery3d.ui.ScreenNail;
 import com.android.gallery3d.ui.SynchronizedHandler;
@@ -37,11 +42,14 @@
 import com.android.gallery3d.ui.TiledScreenNail;
 import com.android.gallery3d.util.Future;
 import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.GifDecoder;
+import com.android.gallery3d.util.GifRequest;
 import com.android.gallery3d.util.MediaSetUtils;
 import com.android.gallery3d.util.ThreadPool;
 import com.android.gallery3d.util.ThreadPool.Job;
 import com.android.gallery3d.util.ThreadPool.JobContext;
 
+import java.lang.Exception;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -49,6 +57,7 @@
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
+import java.util.Locale;
 
 public class PhotoDataAdapter implements PhotoPage.Model {
     @SuppressWarnings("unused")
@@ -66,7 +75,9 @@
 
     private static final int BIT_SCREEN_NAIL = 1;
     private static final int BIT_FULL_IMAGE = 2;
+    private static final int BIT_GIF_ANIMATION = 3;
 
+    private static final long NOTIFY_DIRTY_WAIT_TIME = 10;
     // sImageFetchSeq is the fetching sequence for images.
     // We want to fetch the current screennail first (offset = 0), the next
     // screennail (offset = +1), then the previous screennail (offset = -1) etc.
@@ -85,7 +96,7 @@
 
     static {
         int k = 0;
-        sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3];
+        sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 4];
         sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL);
 
         for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) {
@@ -96,6 +107,7 @@
         sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE);
         sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE);
         sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE);
+        sImageFetchSeq[k++] = new ImageFetch(0, BIT_GIF_ANIMATION);
     }
 
     private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter();
@@ -154,6 +166,10 @@
     private boolean mNeedFullImage;
     private int mFocusHintDirection = FOCUS_HINT_NEXT;
     private Path mFocusHintPath = null;
+    private AbstractGalleryActivity mActivity;
+
+    // If Bundle is from widget, it's true, otherwise it's false.
+    private boolean mIsFromWidget = false;
 
     public interface DataListener extends LoadingListener {
         public void onPhotoChanged(int index, Path item);
@@ -172,6 +188,7 @@
     public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view,
             MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex,
             boolean isPanorama, boolean isStaticCamera) {
+        mActivity = activity;
         mSource = Utils.checkNotNull(mediaSet);
         mPhotoView = Utils.checkNotNull(view);
         mItemPath = Utils.checkNotNull(itemPath);
@@ -292,6 +309,13 @@
         mDataListener = listener;
     }
 
+    /**
+     * Set this to true if it is from widget.
+     */
+    public void setFromWidget(boolean isFromWidget) {
+        mIsFromWidget = isFromWidget;
+    }
+
     private void updateScreenNail(Path path, Future<ScreenNail> future) {
         ImageEntry entry = mImageCache.get(path);
         ScreenNail screenNail = future.get();
@@ -454,6 +478,8 @@
         ImageEntry entry = mImageCache.get(item.getPath());
         if (entry == null) return null;
 
+        ScreenNail targetScreenNail = getTargetScreenNail(entry);
+        if (targetScreenNail != null) return targetScreenNail;
         // Create a default ScreenNail if the real one is not available yet,
         // except for camera that a black screen is better than a gray tile.
         if (entry.screenNail == null && !isCamera(offset)) {
@@ -506,9 +532,16 @@
     @Override
     public boolean isVideo(int offset) {
         MediaItem item = getItem(mCurrentIndex + offset);
-        return (item == null)
-                ? false
-                : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO;
+        return (item == null) ? false
+                : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO
+                        || item.getMediaType() == MediaItem.MEDIA_TYPE_DRM_VIDEO;
+    }
+
+    @Override
+    public boolean isGif(int offset) {
+        MediaItem item = getItem(mCurrentIndex + offset);
+        return (item != null) &&
+                MediaItem.MIME_TYPE_GIF.equalsIgnoreCase(item.getMimeType());
     }
 
     @Override
@@ -608,7 +641,7 @@
     }
 
     private void updateTileProvider(ImageEntry entry) {
-        ScreenNail screenNail = entry.screenNail;
+        ScreenNail screenNail = getTargetScreenNail(entry);
         BitmapRegionDecoder fullImage = entry.fullImage;
         if (screenNail != null) {
             if (fullImage != null) {
@@ -625,6 +658,15 @@
         }
     }
 
+
+    private ScreenNail getTargetScreenNail(ImageEntry entry) {
+        if (null == entry) return null;
+        if (null != entry.currentGifFrame){
+            return entry.currentGifFrame;
+        }
+        return entry.screenNail;
+    }
+
     private void updateSlidingWindow() {
         // 1. Update the image window
         int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2,
@@ -653,6 +695,31 @@
         }
     }
 
+    /**
+     * Update the image window and data window for RTL.
+     */
+    private void updateSlidingWindowForRTL() {
+        // 1. Update the image window
+        int nStart = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2,
+                0, Math.max(0, mSize - IMAGE_CACHE_SIZE));
+        int nEnd = Math.min(mSize, nStart + IMAGE_CACHE_SIZE);
+
+        if (mActiveStart == nStart && mActiveEnd == nEnd) {
+            return; // don't need to refresh
+        }
+
+        mActiveStart = nStart;
+        mActiveEnd = nEnd;
+
+        // 2. Update the data window
+        nStart = Utils.clamp(mCurrentIndex - DATA_CACHE_SIZE / 2,
+                0, Math.max(0, mSize - DATA_CACHE_SIZE));
+        nEnd = Math.min(mSize, nStart + DATA_CACHE_SIZE);
+
+        mContentStart = nStart;
+        mContentEnd = nEnd;
+    }
+
     private void updateImageRequests() {
         if (!mIsActive) return;
 
@@ -685,6 +752,12 @@
                 entry.fullImageTask = null;
                 entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION;
             }
+
+            if (entry.gifDecoderTask != null && entry.gifDecoderTask != task) {
+                entry.gifDecoderTask.cancel();
+                entry.gifDecoderTask = null;
+                entry.requestedGif = MediaObject.INVALID_DATA_VERSION;
+            }
         }
     }
 
@@ -734,6 +807,23 @@
         }
     }
 
+
+    private class GifDecoderJob implements Job<GifDecoder> {
+        private MediaItem mItem;
+
+        public GifDecoderJob(MediaItem item) {
+            mItem = item;
+        }
+
+        @Override
+        public GifDecoder run(JobContext jc) {
+            if (isTemporaryItem(mItem)) {
+                return null;
+            }
+            return new GifRequest(mItem.getContentUri(), mActivity).run(jc);
+        }
+    }
+
     // Returns true if we think this is a temporary item created by Camera. A
     // temporary item is an image or a video whose data is still being
     // processed, but an incomplete entry is created first in MediaProvider, so
@@ -782,6 +872,9 @@
         } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null
                 && entry.requestedFullImage == version) {
             return entry.fullImageTask;
+        } else if (which == BIT_GIF_ANIMATION && entry.gifDecoderTask != null
+                && entry.requestedGif == version) {
+            return entry.gifDecoderTask;
         }
 
         if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) {
@@ -802,6 +895,18 @@
             // request full image
             return entry.fullImageTask;
         }
+
+        if (which == BIT_GIF_ANIMATION
+                && (entry.requestedGif != version)
+                && isGif(0)) {
+            entry.requestedGif = version;
+            entry.gifDecoderTask = mThreadPool.submit(
+                    new GifDecoderJob(item),
+                    new GifDecoderListener(item.getPath()));
+            // request gif decoder
+            return entry.gifDecoderTask;
+        }
+
         return null;
     }
 
@@ -831,6 +936,20 @@
                                 item.getWidth(), item.getHeight());
                     }
                 }
+
+                if (Math.abs(i - mCurrentIndex) > 0) {
+                    if (entry.gifDecoderTask != null) {
+                        entry.gifDecoderTask.cancel();
+                        entry.gifDecoderTask = null;
+                    }
+                    entry.gifDecoder = null;
+                    entry.requestedGif = MediaItem.INVALID_DATA_VERSION;
+                    if (null != entry.currentGifFrame) {
+                        //recycle cached gif frame
+                        entry.currentGifFrame.recycle();
+                        entry.currentGifFrame = null;
+                    }
+                }
             } else {
                 entry = new ImageEntry();
                 mImageCache.put(path, entry);
@@ -892,6 +1011,157 @@
         }
     }
 
+    private class GifDecoderListener
+            implements Runnable, FutureListener<GifDecoder> {
+        private final Path mPath;
+        private Future<GifDecoder> mFuture;
+
+        public GifDecoderListener(Path path) {
+            mPath = path;
+        }
+
+        @Override
+        public void onFutureDone(Future<GifDecoder> future) {
+            mFuture = future;
+            if (null != mFuture.get()) {
+                mMainHandler.sendMessage(
+                        mMainHandler.obtainMessage(MSG_RUN_OBJECT, this));
+            }
+        }
+
+        @Override
+        public void run() {
+            updateGifDecoder(mPath, mFuture);
+        }
+    }
+
+    private void updateGifDecoder(Path path,
+                                  Future<GifDecoder> future) {
+
+        ImageEntry entry = mImageCache.get(path);
+        if (entry == null || entry.gifDecoderTask != future) {
+            return;
+        }
+
+        entry.gifDecoderTask = null;
+        entry.gifDecoder = future.get();
+
+        playGif(path);
+        updateImageRequests();
+
+    }
+
+    private void playGif(Path path) {
+        ImageEntry entry = mImageCache.get(path);
+        if (null == entry) return;
+        if (entry.gifDecoder != null && entry.gifDecoder.getFrameCount() != 0) {
+            if (entry.gifDecoder.mWidth <= 0 || entry.gifDecoder.mHeight <= 0) {
+                return;
+            }
+
+            int currentIndex = mCurrentIndex;
+            if (path == getPath(currentIndex)) {
+                GifEntry gifEntry = new GifEntry();
+                gifEntry.gifDecoder = entry.gifDecoder;
+                gifEntry.animatedIndex = currentIndex;
+                gifEntry.entry = entry;
+
+                mMainHandler.sendMessage(
+                        mMainHandler.obtainMessage(MSG_RUN_OBJECT,
+                                new GifRunnable(path, gifEntry)));
+            }
+        }
+    }
+
+    private class GifRunnable implements Runnable {
+
+        private GifEntry mGifEntry;
+        private Path mPath;
+
+        private void free() {
+            if (null != mGifEntry) {
+                if (null != mGifEntry.gifDecoder) {
+                    mGifEntry.gifDecoder.free();
+                    mGifEntry.gifDecoder = null;
+                }
+                mGifEntry = null;
+            }
+        }
+
+        public GifRunnable(Path path, GifEntry gifEntry) {
+            mPath = path;
+            mGifEntry = gifEntry;
+            if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+                free();
+                return;
+            }
+            boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+            MediaItem item = getMediaItem(0);
+            Path currentPath = (item != null ? item.getPath() : null);
+            imageChanged |= path != currentPath;
+            if (imageChanged) {
+                free();
+                return;
+            }
+            mGifEntry.currentFrame = 0;
+            mGifEntry.totalFrameCount = mGifEntry.gifDecoder.getFrameCount();
+            if (mGifEntry.totalFrameCount <= 1) {
+                free();
+                return;
+            }
+        }
+
+        @Override
+        public void run() {
+            if (!mIsActive) {
+                free();
+                return;
+            }
+
+            if (null == mGifEntry || null == mGifEntry.gifDecoder) {
+                free();
+                return;
+            }
+
+            boolean imageChanged = mGifEntry.animatedIndex != mCurrentIndex;
+            MediaItem item = getMediaItem(0);
+            Path currentPath = (item != null ? item.getPath() : null);
+            imageChanged |= mPath != currentPath;
+            if (imageChanged) {
+                free();
+                return;
+            }
+
+            Bitmap frameBitmap = mGifEntry.gifDecoder.getFrameImage(mGifEntry.currentFrame);
+            if (null == frameBitmap) {
+                free();
+                return;
+            }
+            long delay = (long) mGifEntry.gifDecoder.getDelay(mGifEntry.currentFrame);
+            mGifEntry.currentFrame = (mGifEntry.currentFrame + 1) % mGifEntry.totalFrameCount;
+
+            ScreenNail gifFrame = new BitmapScreenNail(frameBitmap);
+            if (mGifEntry.entry.currentGifFrame != null) {
+                mGifEntry.entry.currentGifFrame.recycle();
+                mGifEntry.entry.currentGifFrame = null;
+            }
+            mGifEntry.entry.currentGifFrame = gifFrame;
+            updateTileProvider(mGifEntry.entry);
+            mPhotoView.notifyImageChange(0);
+            mMainHandler.sendMessageDelayed(
+                    mMainHandler.obtainMessage(MSG_RUN_OBJECT, this), delay);
+        }
+    }
+
+
+    private static class GifEntry {
+        public ImageEntry entry;
+        public GifDecoder gifDecoder;
+        public int animatedIndex;
+        public int currentFrame;
+        public int totalFrameCount;
+    }
+
     private static class ImageEntry {
         public BitmapRegionDecoder fullImage;
         public ScreenNail screenNail;
@@ -900,6 +1170,11 @@
         public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION;
         public long requestedFullImage = MediaObject.INVALID_DATA_VERSION;
         public boolean failToLoad = false;
+
+        public GifDecoder gifDecoder;
+        public Future<GifDecoder> gifDecoderTask;
+        public ScreenNail currentGifFrame;
+        public long requestedGif = MediaObject.INVALID_DATA_VERSION;
     }
 
     private class SourceListener implements ContentListener {
@@ -1021,25 +1296,95 @@
 
         @Override
         public void run() {
+            long version = MediaObject.INVALID_DATA_VERSION;
             while (mActive) {
                 synchronized (this) {
-                    if (!mDirty && mActive) {
+                    if (!mDirty && mActive && version != MediaObject.INVALID_DATA_VERSION) {
                         updateLoading(false);
                         Utils.waitWithoutInterrupt(this);
                         continue;
                     }
                 }
                 mDirty = false;
+
+                version = mSource.reload();
+                //if data is not ready, continue to reload
+                if (version == MediaObject.INVALID_DATA_VERSION) {
+                    continue;
+                }
+                if (mSource.isLoading()) {
+                    mDirty = true;
+                    continue;
+                } else {
+                    mSourceVersion = version;
+                }
                 UpdateInfo info = executeAndWait(new GetUpdateInfo());
                 updateLoading(true);
-                long version = mSource.reload();
-                if (info.version != version) {
-                    info.reloadContent = true;
-                    info.size = mSource.getMediaItemCount();
+
+                // Used for delete photo, RTL need to re-decide the slide range.
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())
+                        && mSource.getCurrectSize() == 1 && mCurrentIndex > 0) {
+                    mCurrentIndex = mCurrentIndex - 1;
+                    mSize = mSource.getMediaItemCount();
+                    updateSlidingWindowForRTL();
+                    info = executeAndWait(new GetUpdateInfo());
                 }
-                if (!info.reloadContent) continue;
-                info.items = mSource.getMediaItem(
-                        info.contentStart, info.contentEnd);
+
+                info.size = mSource.getMediaItemCount();
+
+                // Check it is from camera or not
+                boolean isCameraFlag = false;
+                if (mCameraIndex == mCurrentIndex) {
+                    info.items = mSource.getMediaItem(mCameraIndex, 1);
+                    if (info.items.get(0) instanceof CameraShortcutImage
+                            || info.items.get(0) instanceof SnailItem) {
+                        isCameraFlag = true;
+                    }
+                }
+
+                // If RTL, need to descending photos
+                if (!isCameraFlag
+                        && info.contentStart < info.contentEnd
+                        && (View.LAYOUT_DIRECTION_RTL == TextUtils
+                                .getLayoutDirectionFromLocale(Locale.getDefault()))) {
+
+                    // Calculate picture index/range etc..
+                    int nIndex = isCameraFlag ? mCurrentIndex : info.size - mCurrentIndex - 1;
+                    int nStart = Utils.clamp(nIndex - DATA_CACHE_SIZE / 2, 0,
+                            Math.max(0, info.size - DATA_CACHE_SIZE));
+                    info.items = mSource.getMediaItem(nStart, DATA_CACHE_SIZE);
+
+                    // Initialize temporary picture list
+                    ArrayList<MediaItem> mediaItemList = new ArrayList<MediaItem>();
+
+                    // Fetch source, check the first item is camera or not
+                    ArrayList<MediaItem> itemstmpList = mSource.getMediaItem(0, 1);
+                    MediaItem itemstmp = itemstmpList.size() > 0 ? itemstmpList.get(0) : null;
+                    boolean isCameraItem = (itemstmp != null)
+                            && (itemstmp instanceof CameraShortcutImage
+                            || itemstmp instanceof SnailItem);
+                    if (isCameraItem) {
+                        // If it's camera mode, need to put camera to first position
+                        mediaItemList.add(itemstmp);
+                    }
+
+                    // Descending
+                    for (int i = info.items.size() - 1; i >= 0; i--) {
+                        if (isCameraItem && 0 == i) {
+                            continue;
+                        }
+                        mediaItemList.add(info.items.get(i));
+                    }
+                    info.items = (ArrayList<MediaItem>) mediaItemList.clone();
+
+                    // Clear temporary list and free memory immediately
+                    mediaItemList.clear();
+                    mediaItemList = null;
+                } else {
+                    info.items = mSource.getMediaItem(
+                            info.contentStart, info.contentEnd);
+                } // If RTL, need to descending photos end
 
                 int index = MediaSet.INDEX_NOT_FOUND;
 
@@ -1055,7 +1400,16 @@
                     if (item != null && item.getPath() == info.target) {
                         index = info.indexHint;
                     } else {
-                        index = findIndexOfTarget(info);
+                        // If RTL and it's not from widget, the index don't need to be amended
+                        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                                .getLayoutDirectionFromLocale(Locale.getDefault())
+                                && info.contentStart < info.contentEnd
+                                && !mIsFromWidget) {
+                            index = info.size - findIndexOfTarget(info) - 1;
+                        } else {
+                            index = findIndexOfTarget(info);
+                            mIsFromWidget = false;
+                        }
                     }
                 }
 
diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java
old mode 100644
new mode 100755
index 915fdab..6108c8e
--- a/src/com/android/gallery3d/app/PhotoPage.java
+++ b/src/com/android/gallery3d/app/PhotoPage.java
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,30 +23,36 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.nfc.NfcAdapter;
 import android.nfc.NfcAdapter.CreateBeamUrisCallback;
 import android.nfc.NfcEvent;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
+import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
 import android.widget.RelativeLayout;
-import android.widget.ShareActionProvider;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.dualcam3d.ThreeDimensionalActivity;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.ComboAlbum;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.FilterDeleteSet;
 import com.android.gallery3d.data.FilterSource;
-import com.android.gallery3d.data.LocalImage;
 import com.android.gallery3d.data.MediaDetails;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.MediaObject;
@@ -59,8 +65,8 @@
 import com.android.gallery3d.data.SnailItem;
 import com.android.gallery3d.data.SnailSource;
 import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.crop.CropActivity;
-import com.android.gallery3d.picasasource.PicasaSource;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
 import com.android.gallery3d.ui.DetailsHelper;
 import com.android.gallery3d.ui.DetailsHelper.CloseListener;
 import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
@@ -70,18 +76,24 @@
 import com.android.gallery3d.ui.PhotoView;
 import com.android.gallery3d.ui.SelectionManager;
 import com.android.gallery3d.ui.SynchronizedHandler;
+import com.android.gallery3d.util.GDepth;
 import com.android.gallery3d.util.GalleryUtils;
 import com.android.gallery3d.util.UsageStatistics;
+import com.android.gallery3d.util.ViewGifImage;
+
+import java.util.List;
+import java.util.Locale;
+
+//import android.drm.DrmHelper;
 
 public abstract class PhotoPage extends ActivityState implements
-        PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener,
-        PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener {
+        PhotoView.Listener, AppBridge.Server, PhotoPageBottomControls.Delegate,
+        ThreeDButton.Delegate {
     private static final String TAG = "PhotoPage";
 
     private static final int MSG_HIDE_BARS = 1;
     private static final int MSG_ON_FULL_SCREEN_CHANGED = 4;
     private static final int MSG_UPDATE_ACTION_BAR = 5;
-    private static final int MSG_UNFREEZE_GLROOT = 6;
     private static final int MSG_WANT_BARS = 7;
     private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8;
     private static final int MSG_ON_CAMERA_CENTER = 9;
@@ -93,7 +105,6 @@
     private static final int MSG_UPDATE_PANORAMA_UI = 16;
 
     private static final int HIDE_BARS_TIMEOUT = 3500;
-    private static final int UNFREEZE_GLROOT_TIMEOUT = 250;
 
     private static final int REQUEST_SLIDESHOW = 1;
     private static final int REQUEST_CROP = 2;
@@ -105,6 +116,7 @@
     public static final String KEY_MEDIA_SET_PATH = "media-set-path";
     public static final String KEY_MEDIA_ITEM_PATH = "media-item-path";
     public static final String KEY_INDEX_HINT = "index-hint";
+    public static final String KEY_CURRENT_PHOTO_HINT = "currtent_photo_path";
     public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect";
     public static final String KEY_APP_BRIDGE = "app-bridge";
     public static final String KEY_TREAT_BACK_AS_UP = "treat-back-as-up";
@@ -113,6 +125,11 @@
     public static final String KEY_SHOW_WHEN_LOCKED = "show_when_locked";
     public static final String KEY_IN_CAMERA_ROLL = "in_camera_roll";
     public static final String KEY_READONLY = "read-only";
+    public static final String KEY_FROM_VIDEOS_SCREEN = "from-video-screen";
+    public static final String KEY_FROM_TIMELINE_SCREEN = "from-timeline-screen";
+
+    // Bundle key, used for checking whether it is from widget
+    public static final String KEY_IS_FROM_WIDGET = "is_from_widget";
 
     public static final String KEY_ALBUMPAGE_TRANSITION = "albumpage-transition";
     public static final int MSG_ALBUMPAGE_NONE = 0;
@@ -159,9 +176,13 @@
     private SnailAlbum mScreenNailSet;
     private OrientationManager mOrientationManager;
     private boolean mTreatBackAsUp;
+    // Used for checking whether it is from widget
+    private boolean mIsFromWidget;
     private boolean mStartInFilmstrip;
     private boolean mHasCameraScreennailOrPlaceholder = false;
     private boolean mRecenterCameraOnResume = true;
+    private boolean mIsFromVideoScreen;
+    private boolean mIsFromTimelineScreen;
 
     // These are only valid after the panorama callback
     private boolean mIsPanorama;
@@ -186,6 +207,12 @@
 
     private int mLastSystemUiVis = 0;
 
+    private Intent mShareIntent;
+
+    private ThreeDButton m3DButton;
+    private boolean bShow3DButton;
+    private ParseGDepthTask mParseGDepthTask;
+
     private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() {
         @Override
         public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
@@ -254,6 +281,7 @@
     public void onCreate(Bundle data, Bundle restoreState) {
         super.onCreate(data, restoreState);
         mActionBar = mActivity.getGalleryActionBar();
+        mActionBar.setBackGroundTransparent();
         mSelectionManager = new SelectionManager(mActivity, false);
         mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager);
 
@@ -263,6 +291,8 @@
         mApplication = (GalleryApp) ((Activity) mActivity).getApplication();
         mOrientationManager = mActivity.getOrientationManager();
         mActivity.getGLRoot().setOrientationSource(mOrientationManager);
+        mIsFromVideoScreen = data.getBoolean(KEY_FROM_VIDEOS_SCREEN, false);
+        mIsFromTimelineScreen = data.getBoolean(KEY_FROM_TIMELINE_SCREEN, false);
 
         mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
             @Override
@@ -277,6 +307,9 @@
                             mIsPanorama = message.arg1 == 1;
                             mIsPanorama360 = message.arg2 == 1;
                             mBottomControls.refresh();
+                            if (null != m3DButton) {
+                                m3DButton.refresh();
+                            }
                         }
                         break;
                     }
@@ -294,10 +327,6 @@
                         wantBars();
                         break;
                     }
-                    case MSG_UNFREEZE_GLROOT: {
-                        mActivity.getGLRoot().unfreeze();
-                        break;
-                    }
                     case MSG_UPDATE_DEFERRED: {
                         long nextUpdate = mDeferUpdateUntil - SystemClock.uptimeMillis();
                         if (nextUpdate <= 0) {
@@ -362,8 +391,9 @@
                                 panoramaIntent = createSharePanoramaIntent(contentUri);
                             }
                             Intent shareIntent = createShareIntent(mCurrentPhoto);
-
-                            mActionBar.setShareIntents(panoramaIntent, shareIntent, PhotoPage.this);
+                            if (shareIntent != null) {
+                                mActionBar.setShareIntents(panoramaIntent, shareIntent);
+                            }
                             setNfcBeamPushUri(contentUri);
                         }
                         break;
@@ -389,9 +419,22 @@
                 Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)) :
                     null;
         mTreatBackAsUp = data.getBoolean(KEY_TREAT_BACK_AS_UP, false);
+        mIsFromWidget = data.getBoolean(KEY_IS_FROM_WIDGET, false);
         mStartInFilmstrip = data.getBoolean(KEY_START_IN_FILMSTRIP, false);
         boolean inCameraRoll = data.getBoolean(KEY_IN_CAMERA_ROLL, false);
-        mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
+        if (restoreState == null || mSetPathString == null) {
+            mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0);
+        } else {
+            mCurrentIndex = restoreState.getInt(KEY_INDEX_HINT, 0);
+            //we only save index in onSaveState, set itemPath to null to get the right path later
+            itemPath = null;
+        }
+        if ((mCurrentPhoto == null) && (restoreState != null)) {
+            String curPath = restoreState.getString(KEY_CURRENT_PHOTO_HINT, null);
+            if (curPath != null)
+                mCurrentPhoto = (MediaItem)
+                        mActivity.getDataManager().getMediaObject(curPath);
+        }
         if (mSetPathString != null) {
             mShowSpinner = true;
             mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE);
@@ -451,6 +494,9 @@
             mSetPathString = "/filter/delete/{" + mSetPathString + "}";
             mMediaSet = (FilterDeleteSet) mActivity.getDataManager()
                     .getMediaSet(mSetPathString);
+            if (mMediaSet != null && mIsFromTimelineScreen) {
+                mMediaSet.setShowAlbumsetTimeTitle(false);
+            }
             if (mMediaSet == null) {
                 Log.w(TAG, "failed to restore " + mSetPathString);
             }
@@ -473,6 +519,12 @@
             mModel = pda;
             mPhotoView.setModel(mModel);
 
+            // If RTL and from widget, set the flag into PhotoDataAdapter.
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())
+                    && mIsFromWidget) {
+                pda.setFromWidget(mIsFromWidget);
+            }
             pda.setDataListener(new PhotoDataAdapter.DataListener() {
 
                 @Override
@@ -504,7 +556,10 @@
                     if (!mSkipUpdateCurrentPhoto) {
                         if (item != null) {
                             MediaItem photo = mModel.getMediaItem(0);
-                            if (photo != null) updateCurrentPhoto(photo);
+                            if (photo != null) {
+                                mActionBar.setTitle(photo.getName());
+                                updateCurrentPhoto(photo);
+                            }
                         }
                         updateBars();
                     }
@@ -516,13 +571,16 @@
                 public void onLoadingFinished(boolean loadingFailed) {
                     if (!mModel.isEmpty()) {
                         MediaItem photo = mModel.getMediaItem(0);
-                        if (photo != null) updateCurrentPhoto(photo);
+                        if (photo != null) {
+                            updateCurrentPhoto(photo);
+                        } else {
+                            mModel.resume();
+                        }
                     } else if (mIsActive) {
                         // We only want to finish the PhotoPage if there is no
                         // deletion that the user can undo.
                         if (mMediaSet.getNumberOfDeletions() == 0) {
-                            mActivity.getStateManager().finishState(
-                                    PhotoPage.this);
+                            onBackPressed();
                         }
                     }
                 }
@@ -547,6 +605,7 @@
         if (galleryRoot != null) {
             if (mSecureAlbum == null) {
                 mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot);
+                m3DButton = new ThreeDButton(this, mActivity, galleryRoot);
             }
         }
 
@@ -565,6 +624,17 @@
     }
 
     @Override
+    protected void onSaveState(Bundle outState) {
+        if (mCurrentPhoto != null) {
+            outState.putInt(KEY_INDEX_HINT,mCurrentIndex);
+            outState.putString(KEY_CURRENT_PHOTO_HINT, mCurrentPhoto.getFilePath());
+            super.onSaveState(outState);
+        } else {
+            onBackPressed();
+        }
+    }
+
+    @Override
     public void onPictureCenter(boolean isCamera) {
         isCamera = isCamera || (mHasCameraScreennailOrPlaceholder && mAppBridge == null);
         mPhotoView.setWantPictureCenterCallbacks(false);
@@ -583,19 +653,23 @@
         if (mCurrentPhoto == null) {
             return false;
         }
-        switch(control) {
-            case R.id.photopage_bottom_control_edit:
-                return mHaveImageEditor && mShowBars && !mReadOnlyView
-                        && !mPhotoView.getFilmMode()
-                        && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_EDIT) != 0
-                        && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE;
-            case R.id.photopage_bottom_control_panorama:
-                return mIsPanorama;
-            case R.id.photopage_bottom_control_tiny_planet:
-                return mHaveImageEditor && mShowBars
-                        && mIsPanorama360 && !mPhotoView.getFilmMode();
-            default:
-                return false;
+        switch (control) {
+        case R.id.photopage_bottom_controls:
+            return mShowBars;
+        case R.id.photopage_bottom_control_edit:
+            return mHaveImageEditor
+                    && mShowBars
+                    && !mReadOnlyView
+                    && !mPhotoView.getFilmMode()
+                    && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_EDIT) != 0
+                    && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE;
+        case R.id.photopage_bottom_control_share:
+            mShareIntent = new Intent(Intent.ACTION_SEND);
+            return mShowBars;
+        case R.id.photopage_bottom_control_delete:
+            return mShowBars && !mReadOnlyView;
+        default:
+            return false;
         }
     }
 
@@ -605,15 +679,57 @@
             case R.id.photopage_bottom_control_edit:
                 launchPhotoEditor();
                 return;
-            case R.id.photopage_bottom_control_panorama:
-                mActivity.getPanoramaViewHelper()
-                        .showPanorama(mCurrentPhoto.getContentUri());
+            case R.id.photopage_bottom_control_share:
+                 if (mModel != null && mModel.getMediaItem(0) != null) {
+                 Uri uri = mActivity.getDataManager().getContentUri(mModel.getMediaItem(0).getPath());
+                 mActivity.isTopMenuShow = true;
+                 mShareIntent.setType(MenuExecutor.getMimeType(mModel
+                    .getMediaItem(0).getMediaType()));
+                 mShareIntent.putExtra(Intent.EXTRA_STREAM, uri);
+                 String shareTitle = mActivity.getResources().
+                         getString(R.string.share_dialogue_title);
+                 if (uri.toString().contains("file:")) {
+                     Log.d(TAG, "can't share uri started with file://");
+                     return;
+                 }
+                 mActivity.startActivity(Intent.createChooser(mShareIntent,
+                    shareTitle));
+                 }
+                 return;
+
+            case R.id.photopage_bottom_control_delete:
+                 String confirmMsg = null;
+                 confirmMsg = mActivity.getResources().getQuantityString(
+                    R.plurals.delete_selection, 1);
+                 if (mModel != null && mModel.getMediaItem(0) != null) {
+                 Path path = mModel.getMediaItem(0).getPath();
+                 mSelectionManager.deSelectAll();
+                 mSelectionManager.toggle(path);
+                 MenuItem item = null;
+                 mMenuExecutor.onMenuClicked(item, confirmMsg,
+                    mConfirmDialogListener);
+                 }
                 return;
-            case R.id.photopage_bottom_control_tiny_planet:
-                launchTinyPlanet();
-                return;
-            default:
-                return;
+        default:
+            return;
+        }
+    }
+
+    @Override
+    public boolean canDisplay3DButton() {
+        return bShow3DButton && mShowBars
+                && (mPhotoView == null ? false : !mPhotoView.getFilmMode());
+    }
+
+    @Override
+    public void on3DButtonClicked() {
+        if (mCurrentPhoto != null) {
+            Path p = mCurrentPhoto.getPath();
+            Uri uri = mActivity.getDataManager().getContentUri(p);
+            Intent intent = new Intent();
+            intent.setClass(mActivity, ThreeDimensionalActivity.class);
+            intent.setData(uri);
+            mActivity.startActivity(intent);
         }
     }
 
@@ -621,15 +737,21 @@
     private void setupNfcBeamPush() {
         if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return;
 
-        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mActivity);
-        if (adapter != null) {
-            adapter.setBeamPushUris(null, mActivity);
-            adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
-                @Override
-                public Uri[] createBeamUris(NfcEvent event) {
-                    return mNfcPushUris;
-                }
-            }, mActivity);
+        try {
+            NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mActivity);
+            if (adapter != null) {
+                adapter.setBeamPushUris(null, mActivity);
+                adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() {
+                    @Override
+                    public Uri[] createBeamUris(NfcEvent event) {
+                        return mNfcPushUris;
+                    }
+                }, mActivity);
+            }
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
@@ -637,7 +759,7 @@
         mNfcPushUris[0] = uri;
     }
 
-    private static Intent createShareIntent(MediaObject mediaObject) {
+    private Intent createShareIntent(MediaObject mediaObject) {
         int type = mediaObject.getMediaType();
         return new Intent(Intent.ACTION_SEND)
                 .setType(MenuExecutor.getMimeType(type))
@@ -692,9 +814,18 @@
         }
         intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN,
                 mActivity.isFullscreen());
-        ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null),
-                REQUEST_EDIT);
-        overrideTransitionToEditor();
+
+        List<ResolveInfo> resolveInfoList = mActivity.getPackageManager()
+                .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (resolveInfoList != null && resolveInfoList.size() > 0) {
+            if (resolveInfoList.size() == 1) {
+                // only one app can resolve intent, don't use createChooser.
+                mActivity.startActivityForResult(intent, REQUEST_EDIT);
+            } else {
+                mActivity.startActivityForResult(Intent.createChooser(intent, null), REQUEST_EDIT);
+            }
+            overrideTransitionToEditor();
+        }
     }
 
     private void launchSimpleEditor() {
@@ -740,6 +871,7 @@
 
         updateMenuOperations();
         refreshBottomControlsWhenReady();
+        parseGDepth();
         if (mShowDetails) {
             mDetailsHelper.reloadDetails();
         }
@@ -752,10 +884,27 @@
     private void updateCurrentPhoto(MediaItem photo) {
         if (mCurrentPhoto == photo) return;
         mCurrentPhoto = photo;
+        if (mPhotoView == null) {
+            return;
+        }
         if (mPhotoView.getFilmMode()) {
             requestDeferredUpdate();
         } else {
             updateUIForCurrentPhoto();
+
+            // Manage DRM rights while image selection changed. this
+            // flow will comes for both image and video, but here
+            // we will consume rights for image files only.
+            // Do not consume rights of a GIF image and video here.
+            // ViewGifImage will take care of GIF rights consumption stub.
+            // MediaPlayer will handle the video rights consumption stub.
+//            String mime = mCurrentPhoto.getMimeType();
+//            if (!TextUtils.isEmpty(mime) && !mime.equals("image/gif")
+//                    && !mime.startsWith("video/")) {
+//                DrmHelper.manageDrmLicense(mActivity.getAndroidContext(),
+//                        mHandler, mCurrentPhoto.getFilePath(),
+//                        mCurrentPhoto.getMimeType());
+//            }
         }
     }
 
@@ -773,7 +922,7 @@
 
         int supportedOperations = mCurrentPhoto.getSupportedOperations();
         if (mReadOnlyView) {
-            supportedOperations ^= MediaObject.SUPPORT_EDIT;
+            supportedOperations &= ~MediaObject.SUPPORT_EDIT;
         }
         if (mSecureAlbum != null) {
             supportedOperations &= MediaObject.SUPPORT_DELETE;
@@ -782,6 +931,16 @@
             if (!mHaveImageEditor) {
                 supportedOperations &= ~MediaObject.SUPPORT_EDIT;
             }
+           // If current photo page is single item only, to cut some menu items
+           boolean singleItemOnly = mData.getBoolean("SingleItemOnly", false);
+           if (singleItemOnly) {
+               supportedOperations &= ~MediaObject.SUPPORT_DELETE;
+               supportedOperations &= ~MediaObject.SUPPORT_ROTATE;
+               supportedOperations &= ~MediaObject.SUPPORT_SHARE;
+               supportedOperations &= ~MediaObject.SUPPORT_CROP;
+               supportedOperations &= ~MediaObject.SUPPORT_INFO;
+               supportedOperations &= ~MediaObject.SUPPORT_SETAS;
+           }
         }
         MenuExecutor.updateMenuOperation(menu, supportedOperations);
     }
@@ -821,6 +980,9 @@
 
     private void refreshHidingMessage() {
         mHandler.removeMessages(MSG_HIDE_BARS);
+        if (mPhotoView == null) {
+            return;
+        }
         if (!mIsMenuVisible && !mPhotoView.getFilmMode()) {
             mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT);
         }
@@ -873,7 +1035,19 @@
             } else if (mTreatBackAsUp) {
                 onUpPressed();
             } else {
+                if (mMediaSet != null && mIsFromTimelineScreen) {
+                    //if back to TimeLinePage, need show timeline title
+                    mMediaSet.setShowAlbumsetTimeTitle(true);
+                }
                 super.onBackPressed();
+                mActionBar.setBackGroundDefault();
+                int count = mActivity.getStateManager().getStateCount();
+                if (mIsFromVideoScreen || count == 1 || mIsFromTimelineScreen) {
+                    ((GalleryActivity) mActivity).toggleNavBar(true);
+                    if (mModel instanceof PhotoDataAdapter) {
+                        ((PhotoDataAdapter) mModel).setDataListener(null);
+                    }
+                }
             }
         }
     }
@@ -948,7 +1122,7 @@
         mActionBar.createActionBarMenu(R.menu.photo, menu);
         mHaveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*");
         updateMenuOperations();
-        mActionBar.setTitle(mMediaSet != null ? mMediaSet.getName() : "");
+        //mActionBar.setTitle(mMediaSet != null ? mMediaSet.getName() : "");
         return true;
     }
 
@@ -1022,6 +1196,12 @@
             return true;
         }
         int currentIndex = mModel.getCurrentIndex();
+
+        // If RTL, the current index need be revised.
+        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) {
+            currentIndex = mMediaSet.getMediaItemCount() - currentIndex - 1;
+        }
         Path path = current.getPath();
 
         DataManager manager = mActivity.getDataManager();
@@ -1042,7 +1222,7 @@
                         SlideshowPage.class, REQUEST_SLIDESHOW, data);
                 return true;
             }
-            case R.id.action_crop: {
+            /*case R.id.action_crop: {
                 Activity activity = mActivity;
                 Intent intent = new Intent(CropActivity.CROP_ACTION);
                 intent.setClass(activity, CropActivity.class);
@@ -1052,13 +1232,20 @@
                         ? REQUEST_CROP_PICASA
                         : REQUEST_CROP);
                 return true;
-            }
+            }*/
             case R.id.action_trim: {
                 Intent intent = new Intent(mActivity, TrimVideo.class);
                 intent.setData(manager.getContentUri(path));
                 // We need the file path to wrap this into a RandomAccessFile.
-                intent.putExtra(KEY_MEDIA_ITEM_PATH, current.getFilePath());
-                mActivity.startActivityForResult(intent, REQUEST_TRIM);
+                String str = current.getMimeType();
+                if("video/mp4".equals(str) || "video/mpeg4".equals(str)
+                        || "video/3gpp".equals(str) || "video/3gpp2".equals(str)) {
+                    intent.putExtra(KEY_MEDIA_ITEM_PATH, current.getFilePath());
+                    mActivity.startActivityForResult(intent, REQUEST_TRIM);
+                } else {
+                    Toast.makeText(mActivity,mActivity.getString(R.string.can_not_trim),
+                            Toast.LENGTH_SHORT).show();
+                }
                 return true;
             }
             case R.id.action_mute: {
@@ -1071,10 +1258,10 @@
                 launchPhotoEditor();
                 return true;
             }
-            case R.id.action_simple_edit: {
+            /*case R.id.action_simple_edit: {
                 launchSimpleEditor();
                 return true;
-            }
+            }*/
             case R.id.action_details: {
                 if (mShowDetails) {
                     hideDetails();
@@ -1084,20 +1271,31 @@
                 return true;
             }
             case R.id.print: {
-                mActivity.printSelectedImage(manager.getContentUri(path));
+                try {
+                    mActivity.printSelectedImage(manager.getContentUri(path));
+                } catch (SecurityException e) {
+                    e.printStackTrace();
+                    mActivity.finish();
+                }
                 return true;
             }
             case R.id.action_delete:
                 confirmMsg = mActivity.getResources().getQuantityString(
                         R.plurals.delete_selection, 1);
             case R.id.action_setas:
-            case R.id.action_rotate_ccw:
-            case R.id.action_rotate_cw:
+            //case R.id.action_rotate_ccw:
+            //case R.id.action_rotate_cw:
             case R.id.action_show_on_map:
                 mSelectionManager.deSelectAll();
                 mSelectionManager.toggle(path);
                 mMenuExecutor.onMenuClicked(item, confirmMsg, mConfirmDialogListener);
                 return true;
+//            case R.id.action_drm_info:
+//                String filepath = current.getFilePath();
+//                if (DrmHelper.isDrmFile(filepath)) {
+//                    DrmHelper.showDrmInfo(mActivity.getAndroidContext(), filepath);
+//                }
+//                return true;
             default :
                 return false;
         }
@@ -1136,6 +1334,10 @@
             // item is not ready or it is camera preview, ignore
             return;
         }
+        if (item.getMimeType().equals(MediaItem.MIME_TYPE_GIF)) {
+            viewAnimateGif((Activity) mActivity, item.getContentUri());
+            return;
+        }
 
         int supported = item.getSupportedOperations();
         boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0);
@@ -1200,7 +1402,14 @@
         onCommitDeleteImage();  // commit the previous deletion
         mDeletePath = path;
         mDeleteIsFocus = (offset == 0);
-        mMediaSet.addDeletion(path, mCurrentIndex + offset);
+
+        // If RTL, the index need be revised.
+        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) {
+            mMediaSet.addDeletion(path, mMediaSet.getMediaItemCount() - mCurrentIndex - 1);
+        } else {
+            mMediaSet.addDeletion(path, mCurrentIndex + offset);
+        }
     }
 
     @Override
@@ -1221,6 +1430,10 @@
     }
 
     public void playVideo(Activity activity, Uri uri, String title) {
+        if (GalleryUtils.isTelephonyCallInProgress(mActivity)) {
+            Log.w(TAG, "CS/CSVT Call is in progress, can't play video");
+            return;
+        }
         try {
             Intent intent = new Intent(Intent.ACTION_VIEW)
                     .setDataAndType(uri, "video/*")
@@ -1242,7 +1455,8 @@
             if (albumPath == null) {
                 return;
             }
-            if (!albumPath.equalsIgnoreCase(mOriginalSetPathString)) {
+            boolean isClusterType = FilterUtils.isClusterPath(mOriginalSetPathString);
+            if (!albumPath.equalsIgnoreCase(mOriginalSetPathString) && !isClusterType) {
                 // If the edited image is stored in a different album, we need
                 // to start a new activity state to show the new image
                 Bundle data = new Bundle(getData());
@@ -1251,7 +1465,10 @@
                 mActivity.getStateManager().startState(SinglePhotoPage.class, data);
                 return;
             }
-            mModel.setCurrentPhoto(path, mCurrentIndex);
+            if (null != mModel) {
+                mModel.setCurrentPhoto(path, mCurrentIndex);
+                parseGDepth();
+            }
         }
     }
 
@@ -1264,13 +1481,17 @@
         mRecenterCameraOnResume = false;
         switch (requestCode) {
             case REQUEST_EDIT:
-                setCurrentPhotoByIntent(data);
-                break;
-            case REQUEST_CROP:
-                if (resultCode == Activity.RESULT_OK) {
+                if (data.getData() == null) {
+                    onUpPressed();
+                } else {
                     setCurrentPhotoByIntent(data);
                 }
                 break;
+         /*case REQUEST_CROP:
+                if (resultCode == Activity.RESULT_OK) {
+                    setCurrentPhotoByIntent(data);
+                }
+                break;*/
             case REQUEST_CROP_PICASA: {
                 if (resultCode == Activity.RESULT_OK) {
                     Context context = mActivity.getAndroidContext();
@@ -1284,20 +1505,37 @@
                 if (data == null) break;
                 String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH);
                 int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
+
+                // If RTL, the index need be revised.
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    index = mMediaSet.getMediaItemCount() - index - 1;
+                }
                 if (path != null) {
                     mModel.setCurrentPhoto(Path.fromString(path), index);
+                    parseGDepth();
                 }
             }
         }
     }
 
+    private void parseGDepth() {
+        bShow3DButton = false;
+        if (DualCameraEffect.isSupported()) {
+            if (mParseGDepthTask != null
+                    && mParseGDepthTask.getStatus() != AsyncTask.Status.FINISHED) {
+                mParseGDepthTask.cancel(true);
+            }
+            mParseGDepthTask = new ParseGDepthTask();
+            mParseGDepthTask.execute(mCurrentPhoto.getContentUri());
+        }
+    }
+
     @Override
     public void onPause() {
         super.onPause();
         mIsActive = false;
-
-        mActivity.getGLRoot().unfreeze();
-        mHandler.removeMessages(MSG_UNFREEZE_GLROOT);
+        showFullScreen(false);
 
         DetailsHelper.pause();
         // Hide the detail dialog on exit
@@ -1310,30 +1548,39 @@
         mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS);
         refreshBottomControlsWhenReady();
         mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener);
-        if (mShowSpinner) {
-            mActionBar.disableAlbumModeMenu(true);
-        }
+        // if (mShowSpinner) {
+        // mActionBar.disableAlbumModeMenu(true);
+        // }
         onCommitDeleteImage();
         mMenuExecutor.pause();
         if (mMediaSet != null) mMediaSet.clearDeletion();
     }
 
-    @Override
-    public void onCurrentImageUpdated() {
-        mActivity.getGLRoot().unfreeze();
+    private void showFullScreen(boolean show) {
+        Window win = mActivity.getWindow();
+        WindowManager.LayoutParams winParams = win.getAttributes();
+        if (show) {
+            //set full screen
+            winParams.flags |= (WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        } else {
+            //cancel full screen
+            winParams.flags &= (~WindowManager.LayoutParams.FLAG_FULLSCREEN);
+        }
+        win.setAttributes(winParams);
     }
 
+
     @Override
     public void onFilmModeChanged(boolean enabled) {
         refreshBottomControlsWhenReady();
-        if (mShowSpinner) {
+        /*if (mShowSpinner) {
             if (enabled) {
                 mActionBar.enableAlbumModeMenu(
                         GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this);
             } else {
                 mActionBar.disableAlbumModeMenu(true);
             }
-        }
+        }*/
         if (enabled) {
             mHandler.removeMessages(MSG_HIDE_BARS);
             UsageStatistics.onContentViewChanged(
@@ -1347,6 +1594,23 @@
                 UsageStatistics.onContentViewChanged(
                         UsageStatistics.COMPONENT_CAMERA, "Unknown"); // TODO
             }
+
+            // Manage DRM rights while image selection changed. this
+            // flow will comes for both image and video, but here
+            // we will consume rights for image files only.
+            // Do not consume rights of a GIF image and video here.
+            // ViewGifImage will take care of GIF rights consumption stub.
+            // MediaPlayer will handle the video rights consumption stub.
+//            if ((mMediaSet != null && mMediaSet.getMediaItemCount() > 1)
+//                    || !(this instanceof SinglePhotoPage)) {
+//                String mime = mCurrentPhoto.getMimeType();
+//                if (!TextUtils.isEmpty(mime) && !mime.equals("image/gif")
+//                        && !mime.startsWith("video/")) {
+//                    DrmHelper.manageDrmLicense(mActivity.getAndroidContext(),
+//                            mHandler, mCurrentPhoto.getFilePath(),
+//                            mCurrentPhoto.getMimeType());
+//                }
+//            }
         }
     }
 
@@ -1386,30 +1650,32 @@
     @Override
     protected void onResume() {
         super.onResume();
+        //set full screen to hide the status bar
+        showFullScreen(true);
 
-        if (mModel == null) {
-            mActivity.getStateManager().finishState(this);
-            return;
-        }
         transitionFromAlbumPageIfNeeded();
 
-        mActivity.getGLRoot().freeze();
         mIsActive = true;
         setContentPane(mRootPane);
 
-        mModel.resume();
-        mPhotoView.resume();
+        //if from TimeLinePage, don't show the timeline title
+        if (mMediaSet != null && mIsFromTimelineScreen) {
+            mMediaSet.setShowAlbumsetTimeTitle(false);
+        }
+
         mActionBar.setDisplayOptions(
-                ((mSecureAlbum == null) && (mSetPathString != null)), false);
+                (false && (mSetPathString != null)), true);
         mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener);
         refreshBottomControlsWhenReady();
-        if (mShowSpinner && mPhotoView.getFilmMode()) {
-            mActionBar.enableAlbumModeMenu(
-                    GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this);
+        if (((mSecureAlbum == null) && (mSetPathString != null))) {
+            ((GalleryActivity) mActivity).toggleNavBar(false);
         }
+        // if (mShowSpinner && mPhotoView.getFilmMode()) {
+        // mActionBar.enableAlbumModeMenu(
+        // GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this);
+        // }
         if (!mShowBars) {
             mActionBar.hide();
-            mActivity.getGLRoot().setLightsOutMode(true);
         }
         boolean haveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*");
         if (haveImageEditor != mHaveImageEditor) {
@@ -1418,7 +1684,12 @@
         }
 
         mRecenterCameraOnResume = true;
-        mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT);
+        if (mModel == null) {
+            onBackPressed();
+            return;
+        }
+        mModel.resume();
+        mPhotoView.resume();
     }
 
     @Override
@@ -1433,7 +1704,9 @@
         }
         mActivity.getGLRoot().setOrientationSource(null);
         if (mBottomControls != null) mBottomControls.cleanup();
-
+        if (m3DButton != null) m3DButton.cleanup();
+        mPhotoView.destroy();
+        mPhotoView = null;
         // Remove all pending messages.
         mHandler.removeCallbacksAndMessages(null);
         super.onDestroy();
@@ -1457,12 +1730,12 @@
         }
     }
 
-    @Override
+    /*@Override
     public void onAlbumModeSelected(int mode) {
         if (mode == GalleryActionBar.ALBUM_GRID_MODE_SELECTED) {
             switchToGrid();
         }
-    }
+    }*/
 
     @Override
     public void refreshBottomControlsWhenReady() {
@@ -1507,19 +1780,6 @@
         refreshBottomControlsWhenReady();
     }
 
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
-        final long timestampMillis = mCurrentPhoto.getDateInMs();
-        final String mediaType = getMediaTypeString(mCurrentPhoto);
-        UsageStatistics.onEvent(UsageStatistics.COMPONENT_GALLERY,
-                UsageStatistics.ACTION_SHARE,
-                mediaType,
-                        timestampMillis > 0
-                        ? System.currentTimeMillis() - timestampMillis
-                        : -1);
-        return false;
-    }
-
     private static String getMediaTypeString(MediaItem item) {
         if (item.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO) {
             return "Video";
@@ -1530,4 +1790,22 @@
         }
     }
 
+    private class ParseGDepthTask extends AsyncTask<Uri, Void, Boolean> {
+        @Override
+        protected Boolean doInBackground(Uri... params) {
+            GDepth.Parser parser = new GDepth.Parser();
+            return parser.parse(mActivity, params[0]);
+        }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+            bShow3DButton = !isCancelled() && result;
+            m3DButton.refresh();
+        }
+    }
+
+    private static void viewAnimateGif(Activity activity, Uri uri) {
+        Intent intent = new Intent(ViewGifImage.VIEW_GIF_ACTION, uri);
+        activity.startActivity(intent);
+    }
 }
diff --git a/src/com/android/gallery3d/app/PhotoPageBottomControls.java b/src/com/android/gallery3d/app/PhotoPageBottomControls.java
index 57f8b6f..166224e 100644
--- a/src/com/android/gallery3d/app/PhotoPageBottomControls.java
+++ b/src/com/android/gallery3d/app/PhotoPageBottomControls.java
@@ -17,6 +17,8 @@
 package com.android.gallery3d.app;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -24,8 +26,9 @@
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.widget.RelativeLayout;
+import android.widget.ImageButton;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -50,6 +53,7 @@
     private static final int CONTAINER_ANIM_DURATION_MS = 200;
 
     private static final int CONTROL_ANIM_DURATION_MS = 150;
+
     private static Animation getControlAnimForVisibility(boolean visible) {
         Animation anim = visible ? new AlphaAnimation(0f, 1f)
                 : new AlphaAnimation(1f, 0f);
@@ -66,11 +70,12 @@
         mContainer = (ViewGroup) inflater
                 .inflate(R.layout.photopage_bottom_controls, mParentLayout, false);
         mParentLayout.addView(mContainer);
-
         for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
             View child = mContainer.getChildAt(i);
             child.setOnClickListener(this);
             mControlsVisible.put(child, false);
+            if (i == 0)
+                mControlsVisible.put(mContainer, false);
         }
 
         mContainerAnimIn.setDuration(CONTAINER_ANIM_DURATION_MS);
@@ -115,7 +120,7 @@
                     control.clearAnimation();
                     control.startAnimation(getControlAnimForVisibility(curVisibility));
                 }
-                control.setVisibility(curVisibility ? View.VISIBLE : View.INVISIBLE);
+                control.setVisibility(curVisibility ? View.VISIBLE : View.GONE);
                 mControlsVisible.put(control, curVisibility);
             }
         }
diff --git a/src/com/android/gallery3d/app/PhotoPageProgressBar.java b/src/com/android/gallery3d/app/PhotoPageProgressBar.java
index 141fea6..788a6b8 100644
--- a/src/com/android/gallery3d/app/PhotoPageProgressBar.java
+++ b/src/com/android/gallery3d/app/PhotoPageProgressBar.java
@@ -22,7 +22,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.widget.RelativeLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class PhotoPageProgressBar {
     private ViewGroup mContainer;
diff --git a/src/com/android/gallery3d/app/PickerActivity.java b/src/com/android/gallery3d/app/PickerActivity.java
index d5bb218..78d0f25 100644
--- a/src/com/android/gallery3d/app/PickerActivity.java
+++ b/src/com/android/gallery3d/app/PickerActivity.java
@@ -24,7 +24,7 @@
 import android.view.View.OnClickListener;
 import android.view.Window;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ui.GLRootView;
 
 public class PickerActivity extends AbstractGalleryActivity
@@ -80,4 +80,14 @@
     public void onClick(View v) {
         if (v.getId() == R.id.cancel) finish();
     }
+
+    @Override
+    protected void onGetPermissionsSuccess() {
+
+    }
+
+    @Override
+    protected void onGetPermissionsFailure() {
+
+    }
 }
diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
old mode 100644
new mode 100755
index 00f2fe7..0a18a27
--- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
+++ b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java
@@ -89,7 +89,16 @@
         @Override
         public void onFutureDone(Future<BitmapRegionDecoder> future) {
             BitmapRegionDecoder decoder = future.get();
-            if (decoder == null) return;
+            // cannot get large bitmap, then try to get thumb bitmap
+            if (decoder == null) {
+                if (mTask != null && !mTask.isCancelled()) {
+                    Log.w(TAG, "fail to get region decoder, try to request thumb image");
+                    mHasFullImage = false;
+                    pause();
+                    resume();
+                }
+                return;
+            }
             int width = decoder.getWidth();
             int height = decoder.getHeight();
             BitmapFactory.Options options = new BitmapFactory.Options();
@@ -136,7 +145,6 @@
             Bitmap backup = future.get();
             if (backup == null) {
                 mLoadingState = LOADING_FAIL;
-                return;
             } else {
                 mLoadingState = LOADING_COMPLETE;
             }
@@ -164,11 +172,10 @@
     @Override
     public void pause() {
         Future<?> task = mTask;
-        task.cancel();
-        task.waitDone();
-        if (task.get() == null) {
-            mTask = null;
+        if (!task.isDone()) {
+            task.cancel();
         }
+        mTask = null;
         if (mBitmapScreenNail != null) {
             mBitmapScreenNail.recycle();
             mBitmapScreenNail = null;
@@ -227,6 +234,11 @@
     }
 
     @Override
+    public boolean isGif(int offset) {
+        return MediaItem.MIME_TYPE_GIF.equalsIgnoreCase(mItem.getMimeType());
+    }
+
+    @Override
     public boolean isDeletable(int offset) {
         return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0;
     }
diff --git a/src/com/android/gallery3d/app/SlideshowDataAdapter.java b/src/com/android/gallery3d/app/SlideshowDataAdapter.java
index 7a0fba5..50f8ac2 100644
--- a/src/com/android/gallery3d/app/SlideshowDataAdapter.java
+++ b/src/com/android/gallery3d/app/SlideshowDataAdapter.java
@@ -189,7 +189,6 @@
         }
         mSource.removeContentListener(mSourceListener);
         mReloadTask.cancel();
-        mReloadTask.waitDone();
         mReloadTask = null;
     }
 
diff --git a/src/com/android/gallery3d/app/SlideshowPage.java b/src/com/android/gallery3d/app/SlideshowPage.java
index 174058d..29df606 100644
--- a/src/com/android/gallery3d/app/SlideshowPage.java
+++ b/src/com/android/gallery3d/app/SlideshowPage.java
@@ -16,15 +16,19 @@
 
 package com.android.gallery3d.app;
 
+import java.util.ArrayList;
+import java.util.Random;
+
 import android.app.Activity;
 import android.content.Intent;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.ContentListener;
 import com.android.gallery3d.data.MediaItem;
@@ -38,9 +42,6 @@
 import com.android.gallery3d.util.Future;
 import com.android.gallery3d.util.FutureListener;
 
-import java.util.ArrayList;
-import java.util.Random;
-
 public class SlideshowPage extends ActivityState {
     private static final String TAG = "SlideshowPage";
 
@@ -112,7 +113,9 @@
     @Override
     public void onCreate(Bundle data, Bundle restoreState) {
         super.onCreate(data, restoreState);
-        mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR);
+        ((GalleryActivity) mActivity).toggleNavBar(false);
+
+        mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR | FLAG_SCREEN_FULL);
         if (data.getBoolean(KEY_DREAM)) {
             // Dream screensaver only keeps screen on for plugged devices.
             mFlags |= FLAG_SCREEN_ON_WHEN_PLUGGED | FLAG_SHOW_WHEN_LOCKED;
@@ -137,6 +140,7 @@
         };
         initializeViews();
         initializeData(data);
+        Log.d(GalleryActivity.QSST, "enter slide show successfully");
     }
 
     private void loadNextBitmap() {
@@ -172,6 +176,9 @@
     @Override
     public void onPause() {
         super.onPause();
+        if (mActivity.getStateManager().getStateCount() <= 1) {
+            ((GalleryActivity) mActivity).toggleNavBar(true);
+        }
         mIsActive = false;
         mModel.pause();
         mSlideshowView.release();
@@ -183,6 +190,7 @@
     @Override
     public void onResume() {
         super.onResume();
+        ((GalleryActivity) mActivity).toggleNavBar(false);
         mIsActive = true;
         mModel.resume();
 
@@ -338,6 +346,15 @@
                 mData = mMediaSet.getMediaItem(index, DATA_SIZE);
                 mDataStart = index;
                 dataEnd = index + mData.size();
+
+                // Consume license once in each element of the slide-show
+                // This is a non-blocking loop operation
+//                for (int i = 0; i < mData.size(); i++) {
+//                    String path = mData.get(i).getFilePath();
+//                    if (DrmHelper.isDrmFile(path)) {
+//                        DrmHelper.consumeDrmRights(path, "image/*");
+//                    }
+//                }
             }
 
             return (index < mDataStart || index >= dataEnd) ? null : mData.get(index - mDataStart);
diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java
index aa372a8..40a7130 100644
--- a/src/com/android/gallery3d/app/StateManager.java
+++ b/src/com/android/gallery3d/app/StateManager.java
@@ -130,7 +130,9 @@
     }
 
     public void notifyActivityResult(int requestCode, int resultCode, Intent data) {
-        getTopState().onStateResult(requestCode, resultCode, data);
+        if (!mStack.isEmpty()) {
+            getTopState().onStateResult(requestCode, resultCode, data);
+        }
     }
 
     public void clearActivityResult() {
diff --git a/src/com/android/gallery3d/app/ThreeDButton.java b/src/com/android/gallery3d/app/ThreeDButton.java
new file mode 100644
index 0000000..4cc146a
--- /dev/null
+++ b/src/com/android/gallery3d/app/ThreeDButton.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.widget.RelativeLayout;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDButton implements OnClickListener {
+    interface Delegate {
+        boolean canDisplay3DButton();
+
+        void on3DButtonClicked();
+    }
+
+    private Delegate mDelegate;
+    private ViewGroup root;
+    private ViewGroup mContainer;
+    private boolean mContainerVisible = false;
+
+    private Animation mAnimIn = new AlphaAnimation(0f, 1f);
+    private Animation mAnimOut = new AlphaAnimation(1f, 0f);
+    private static final int ANIM_DURATION = 200;
+
+    public ThreeDButton(Delegate delegate, Context context, RelativeLayout layout) {
+        mDelegate = delegate;
+        root = layout;
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mContainer = (ViewGroup) inflater
+                .inflate(R.layout.three_d_button, root, false);
+        mContainer.findViewById(R.id.three_dimensional).setOnClickListener(this);
+        root.addView(mContainer);
+        mAnimIn.setDuration(ANIM_DURATION);
+        mAnimOut.setDuration(ANIM_DURATION);
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (mContainer.getVisibility() == View.VISIBLE) {
+            mDelegate.on3DButtonClicked();
+        }
+    }
+
+    public void refresh() {
+        boolean visible = mDelegate.canDisplay3DButton();
+        if (visible != mContainerVisible) {
+            if (visible) {
+                show();
+            } else {
+                hide();
+            }
+            mContainerVisible = visible;
+        }
+    }
+
+    private void hide() {
+        mContainer.clearAnimation();
+        mAnimOut.reset();
+        mContainer.startAnimation(mAnimOut);
+        mContainer.setVisibility(View.GONE);
+    }
+
+    private void show() {
+        mContainer.clearAnimation();
+        mAnimIn.reset();
+        mContainer.startAnimation(mAnimIn);
+        mContainer.setVisibility(View.VISIBLE);
+    }
+
+    public void cleanup() {
+        root.removeView(mContainer);
+    }
+
+}
diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java
old mode 100644
new mode 100755
index 246346a..976335a
--- a/src/com/android/gallery3d/app/TimeBar.java
+++ b/src/com/android/gallery3d/app/TimeBar.java
@@ -22,13 +22,17 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.text.TextUtils;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 
+import java.util.Locale;
+
 /**
  * The time bar view, which includes the current and total time, the progress
  * bar, and the scrubber.
@@ -44,13 +48,17 @@
     }
 
     // Padding around the scrubber to increase its touch target
-    private static final int SCRUBBER_PADDING_IN_DP = 10;
+    private static final int SCRUBBER_PADDING_IN_DP = 3;
 
     // The total padding, top plus bottom
     private static final int V_PADDING_IN_DP = 30;
 
     private static final int TEXT_SIZE_IN_DP = 14;
 
+    private static final String TAG = "Gallery3D/TimeBar";
+    private static final boolean LOG = false;
+    public static final int UNKNOWN = -1;
+
     protected final Listener mListener;
 
     // the bars we use for displaying the progress
@@ -71,6 +79,7 @@
     protected boolean mScrubbing;
     protected boolean mShowTimes;
     protected boolean mShowScrubber;
+    private boolean mEnableScrubbing;
 
     protected int mTotalTime;
     protected int mCurrentTime;
@@ -78,6 +87,11 @@
     protected final Rect mTimeBounds;
 
     protected int mVPaddingInPx;
+    private int mLastShowTime = UNKNOWN;
+
+    private ITimeBarSecondaryProgressExt mSecondaryProgressExt = new TimeBarSecondaryProgressExtImpl();
+    private ITimeBarInfoExt mInfoExt = new TimeBarInfoExtImpl();
+    protected ITimeBarLayoutExt mLayoutExt = new TimeBarLayoutExtImpl();
 
     public TimeBar(Context context, Listener listener) {
         super(context);
@@ -92,7 +106,7 @@
         mProgressPaint = new Paint();
         mProgressPaint.setColor(0xFF808080);
         mPlayedPaint = new Paint();
-        mPlayedPaint.setColor(0xFFFFFFFF);
+        mPlayedPaint.setColor(0xFF4F92E9);
 
         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
         float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP;
@@ -108,21 +122,53 @@
         mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP);
 
         mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP);
+        mLayoutExt.init(mScrubberPadding, mVPaddingInPx);
+        mInfoExt.init(textSizeInPx);
+        mSecondaryProgressExt.init();
     }
 
     private void update() {
         mPlayedBar.set(mProgressBar);
 
         if (mTotalTime > 0) {
-            mPlayedBar.right =
-                    mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                // The progress bar should be reversed in RTL.
+                mPlayedBar.left = mPlayedBar.right
+                        - (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+            } else {
+                mPlayedBar.right = mPlayedBar.left
+                        + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime);
+            }
+            /*
+             * M: if duration is not accurate, here just adjust playedBar we
+             * also show the accurate position text to final user.
+             */
+            if (mPlayedBar.right > mProgressBar.right) {
+                mPlayedBar.right = mProgressBar.right;
+            }
         } else {
-            mPlayedBar.right = mProgressBar.left;
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                // The progress bar should be reversed in RTL.
+                mPlayedBar.left = mProgressBar.right;
+            } else {
+                mPlayedBar.right = mProgressBar.left;
+            }
         }
 
         if (!mScrubbing) {
-            mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils.getLayoutDirectionFromLocale(
+                    Locale.getDefault())) {
+                // The progress bar should be reversed in RTL.
+                mScrubberLeft = mPlayedBar.left - mScrubber.getWidth() / 2;
+            } else {
+                mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2;
+            }
         }
+        // update text bounds when layout changed or time changed
+        updateBounds();
+        mInfoExt.updateVisibleText(this, mProgressBar, mTimeBounds);
         invalidate();
     }
 
@@ -130,14 +176,16 @@
      * @return the preferred height of this view, including invisible padding
      */
     public int getPreferredHeight() {
-        return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
+        int preferredHeight = mTimeBounds.height() + mVPaddingInPx + mScrubberPadding;
+        return mLayoutExt.getPreferredHeight(preferredHeight, mTimeBounds);
     }
 
     /**
      * @return the height of the time bar, excluding invisible padding
      */
     public int getBarHeight() {
-        return mTimeBounds.height() + mVPaddingInPx;
+        int barHeight = mTimeBounds.height() + mVPaddingInPx;
+        return mLayoutExt.getBarHeight(barHeight, mTimeBounds);
     }
 
     public void setTime(int currentTime, int totalTime,
@@ -146,7 +194,10 @@
             return;
         }
         mCurrentTime = currentTime;
-        mTotalTime = totalTime;
+        mTotalTime = Math.abs(totalTime);
+        if (totalTime <= 0) { /// M: disable scrubbing before mediaplayer ready.
+            setScrubbing(false);
+        }
         update();
     }
 
@@ -165,9 +216,17 @@
     }
 
     private int getScrubberTime() {
-        return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
-                * mTotalTime / mProgressBar.width());
-    }
+        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) {
+            // The progress bar's scrubber time should be reversed in RTL.
+            return (int) ((long) (mProgressBar.width() - (mScrubberLeft
+                    + mScrubber.getWidth() / 2 - mProgressBar.left))
+                    * mTotalTime / mProgressBar.width());
+        } else {
+            return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left)
+                    * mTotalTime / mProgressBar.width());
+        }
+  }
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
@@ -180,19 +239,22 @@
             if (mShowTimes) {
                 margin += mTimeBounds.width();
             }
-            int progressY = (h + mScrubberPadding) / 2;
+            margin = mLayoutExt.getProgressMargin(margin);
+            int progressY = (h + mScrubberPadding) / 2 + mLayoutExt.getProgressOffset(mTimeBounds);
             mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1;
             mProgressBar.set(
                     getPaddingLeft() + margin, progressY,
-                    w - getPaddingRight() - margin, progressY + 4);
+                    w - getPaddingRight() - margin, progressY + 6);
         }
         update();
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
         // draw progress bars
         canvas.drawRect(mProgressBar, mProgressPaint);
+        mSecondaryProgressExt.draw(canvas, mProgressBar);
         canvas.drawRect(mPlayedBar, mPlayedPaint);
 
         // draw scrubber and timers
@@ -200,22 +262,44 @@
             canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null);
         }
         if (mShowTimes) {
-            canvas.drawText(
-                    stringForTime(mCurrentTime),
-                            mTimeBounds.width() / 2 + getPaddingLeft(),
-                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
-                    mTimeTextPaint);
-            canvas.drawText(
-                    stringForTime(mTotalTime),
-                            getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
-                            mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
-                    mTimeTextPaint);
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                // The progress bar's time should be reversed in RTL.
+                canvas.drawText(
+                        stringForTime(mCurrentTime),
+                        getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+                        mTimeTextPaint);
+                canvas.drawText(
+                        stringForTime(mTotalTime),
+                        mTimeBounds.width() / 2 + getPaddingLeft(),
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+                        mTimeTextPaint);
+            } else {
+                canvas.drawText(
+                        stringForTime(mCurrentTime),
+                        mTimeBounds.width() / 2 + getPaddingLeft(),
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+                        mTimeTextPaint);
+                canvas.drawText(
+                        stringForTime(mTotalTime),
+                        getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1,
+                        mTimeTextPaint);
+            }
         }
+        mInfoExt.draw(canvas, mLayoutExt.getInfoBounds(this, mTimeBounds));
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        if (mShowScrubber) {
+        if (LOG) {
+            Log.v(TAG, "onTouchEvent() showScrubber=" + mShowScrubber
+                    + ", enableScrubbing=" + mEnableScrubbing + ", totalTime="
+                    + mTotalTime + ", scrubbing=" + mScrubbing + ", event="
+                    + event);
+        }
+        if (mShowScrubber && mEnableScrubbing) {
             int x = (int) event.getX();
             int y = (int) event.getY();
 
@@ -233,15 +317,19 @@
                     clampScrubber();
                     mCurrentTime = getScrubberTime();
                     mListener.onScrubbingMove(mCurrentTime);
+                    update();
                     invalidate();
                     return true;
                 }
                 case MotionEvent.ACTION_CANCEL:
-                case MotionEvent.ACTION_UP: {
-                    mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
-                    mScrubbing = false;
-                    return true;
-                }
+                case MotionEvent.ACTION_UP:
+                    if (mScrubbing) {
+                        mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
+                        mScrubbing = false;
+                        update();
+                        return true;
+                    }
+                    break;
             }
         }
         return false;
@@ -263,4 +351,235 @@
         mShowScrubber = canSeek;
     }
 
+    private void updateBounds() {
+        int showTime = mTotalTime > mCurrentTime ? mTotalTime : mCurrentTime;
+        if (mLastShowTime == showTime) {
+            // do not need to recompute the bounds.
+            return;
+        }
+        String durationText = stringForTime(showTime);
+        int length = durationText.length();
+        mTimeTextPaint.getTextBounds(durationText, 0, length, mTimeBounds);
+        mLastShowTime = showTime;
+        if (LOG) {
+            Log.v(TAG, "updateBounds() durationText=" + durationText + ", timeBounds="
+                    + mTimeBounds);
+        }
+    }
+
+    public void setScrubbing(boolean enable) {
+        if (LOG) {
+            Log.v(TAG, "setScrubbing(" + enable + ") scrubbing=" + mScrubbing);
+        }
+        mEnableScrubbing = enable;
+        if (mScrubbing) { // if it is scrubbing, change it to false
+            mListener.onScrubbingEnd(getScrubberTime(), 0, 0);
+            mScrubbing = false;
+        }
+    }
+
+    public boolean getScrubbing() {
+        if (LOG) {
+            Log.v(TAG, "mEnableScrubbing=" + mEnableScrubbing);
+        }
+        return mEnableScrubbing;
+    }
+
+    public void setInfo(String info) {
+        if (LOG) {
+            Log.v(TAG, "setInfo(" + info + ")");
+        }
+        mInfoExt.setInfo(info);
+        mInfoExt.updateVisibleText(this, mProgressBar, mTimeBounds);
+        invalidate();
+    }
+
+    public void setSecondaryProgress(int percent) {
+        if (LOG) {
+            Log.v(TAG, "setSecondaryProgress(" + percent + ")");
+        }
+        mSecondaryProgressExt.setSecondaryProgress(mProgressBar, percent);
+        invalidate();
+    }
+}
+
+interface ITimeBarInfoExt {
+    void init(float textSizeInPx);
+
+    void setInfo(String info);
+
+    void draw(Canvas canvas, Rect infoBounds);
+
+    void updateVisibleText(View parent, Rect progressBar, Rect timeBounds);
+}
+
+interface ITimeBarSecondaryProgressExt {
+    void init();
+
+    void setSecondaryProgress(Rect progressBar, int percent);
+
+    void draw(Canvas canvas, Rect progressBounds);
+}
+
+interface ITimeBarLayoutExt {
+    void init(int scrubberPadding, int vPaddingInPx);
+
+    int getPreferredHeight(int originalPreferredHeight, Rect timeBounds);
+
+    int getBarHeight(int originalBarHeight, Rect timeBounds);
+
+    int getProgressMargin(int originalMargin);
+
+    int getProgressOffset(Rect timeBounds);
+
+    int getTimeOffset();
+
+    Rect getInfoBounds(View parent, Rect timeBounds);
+}
+
+class TimeBarInfoExtImpl implements ITimeBarInfoExt {
+    private static final String TAG = "TimeBarInfoExtensionImpl";
+    private static final boolean LOG = false;
+    private static final String ELLIPSE = "...";
+
+    private Paint mInfoPaint;
+    private Rect mInfoBounds;
+    private String mInfoText;
+    private String mVisibleText;
+    private int mEllipseLength;
+
+    @Override
+    public void init(float textSizeInPx) {
+        mInfoPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        mInfoPaint.setColor(0xFFCECECE);
+        mInfoPaint.setTextSize(textSizeInPx);
+        mInfoPaint.setTextAlign(Paint.Align.CENTER);
+
+        mEllipseLength = (int) Math.ceil(mInfoPaint.measureText(ELLIPSE));
+    }
+
+    @Override
+    public void draw(Canvas canvas, Rect infoBounds) {
+        if (mInfoText != null && mVisibleText != null) {
+            canvas.drawText(mVisibleText, infoBounds.centerX(), infoBounds.centerY(), mInfoPaint);
+        }
+    }
+
+    @Override
+    public void setInfo(String info) {
+        mInfoText = info;
+    }
+
+    public void updateVisibleText(View parent, Rect progressBar, Rect timeBounds) {
+        if (mInfoText == null) {
+            mVisibleText = null;
+            return;
+        }
+        float tw = mInfoPaint.measureText(mInfoText);
+        float space = progressBar.width() - timeBounds.width() * 2 - parent.getPaddingLeft()
+                - parent.getPaddingRight();
+        if (tw > 0 && space > 0 && tw > space) {
+            // we need to cut the info text for visible
+            float originalNum = mInfoText.length();
+            int realNum = (int) ((space - mEllipseLength) * originalNum / tw);
+            if (LOG) {
+                Log.v(TAG, "updateVisibleText() infoText=" + mInfoText + " text width=" + tw
+                        + ", space=" + space + ", originalNum=" + originalNum + ", realNum="
+                        + realNum
+                        + ", getPaddingLeft()=" + parent.getPaddingLeft() + ", getPaddingRight()="
+                        + parent.getPaddingRight()
+                        + ", progressBar=" + progressBar + ", timeBounds=" + timeBounds);
+            }
+            mVisibleText = mInfoText.substring(0, realNum) + ELLIPSE;
+        } else {
+            mVisibleText = mInfoText;
+        }
+        if (LOG) {
+            Log.v(TAG, "updateVisibleText() infoText=" + mInfoText + ", visibleText="
+                    + mVisibleText
+                    + ", text width=" + tw + ", space=" + space);
+        }
+    }
+}
+
+class TimeBarSecondaryProgressExtImpl implements ITimeBarSecondaryProgressExt {
+    private static final String TAG = "TimeBarSecondaryProgressExtensionImpl";
+    private static final boolean LOG = false;
+
+    private int mBufferPercent;
+    private Rect mSecondaryBar;
+    private Paint mSecondaryPaint;
+
+    @Override
+    public void init() {
+        mSecondaryBar = new Rect();
+        mSecondaryPaint = new Paint();
+        mSecondaryPaint.setColor(0xFF5CA0C5);
+    }
+
+    @Override
+    public void draw(Canvas canvas, Rect progressBounds) {
+        if (mBufferPercent >= 0) {
+            mSecondaryBar.set(progressBounds);
+            mSecondaryBar.right = mSecondaryBar.left
+                    + (int) (mBufferPercent * progressBounds.width() / 100);
+            canvas.drawRect(mSecondaryBar, mSecondaryPaint);
+        }
+        if (LOG) {
+            Log.v(TAG, "draw() bufferPercent=" + mBufferPercent + ", secondaryBar="
+                    + mSecondaryBar);
+        }
+    }
+
+    @Override
+    public void setSecondaryProgress(Rect progressBar, int percent) {
+        mBufferPercent = percent;
+    }
+}
+
+class TimeBarLayoutExtImpl implements ITimeBarLayoutExt {
+    private static final String TAG = "TimeBarLayoutExtensionImpl";
+    private static final boolean LOG = false;
+
+    private int mTextPadding;
+    private int mVPaddingInPx;
+
+    @Override
+    public void init(int scrubberPadding, int vPaddingInPx) {
+        mTextPadding = scrubberPadding / 2;
+        mVPaddingInPx = vPaddingInPx;
+    }
+
+    @Override
+    public int getPreferredHeight(int originalPreferredHeight, Rect timeBounds) {
+        return originalPreferredHeight + timeBounds.height() + mTextPadding;
+    }
+
+    @Override
+    public int getBarHeight(int originalBarHeight, Rect timeBounds) {
+        return originalBarHeight + timeBounds.height() + mTextPadding;
+    }
+
+    @Override
+    public int getProgressMargin(int originalMargin) {
+        return 0;
+    }
+
+    @Override
+    public int getProgressOffset(Rect timeBounds) {
+        return (timeBounds.height() + mTextPadding) / 2;
+    }
+
+    @Override
+    public int getTimeOffset() {
+        return mTextPadding - mVPaddingInPx / 2;
+    }
+
+    @Override
+    public Rect getInfoBounds(View parent, Rect timeBounds) {
+        Rect bounds = new Rect(parent.getPaddingLeft(), 0,
+                parent.getWidth() - parent.getPaddingRight(),
+                (timeBounds.height() + mTextPadding * 3 + 1) * 2);
+        return bounds;
+    }
 }
diff --git a/src/com/android/gallery3d/app/TimeBarNew.java b/src/com/android/gallery3d/app/TimeBarNew.java
new file mode 100644
index 0000000..28211d6
--- /dev/null
+++ b/src/com/android/gallery3d/app/TimeBarNew.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app;
+
+import android.content.Context;
+import android.view.MotionEvent;
+
+import org.codeaurora.gallery.R;
+
+public class TimeBarNew extends TimeBar {
+
+    private int mTimeBarHeight;
+
+    public TimeBarNew(Context context, Listener listener) {
+        super(context, listener);
+        mTimeBarHeight = context.getResources().getDimensionPixelSize(R.dimen.timebar_height);
+        this.setClickable(true);
+    }
+
+    @Override
+    public int getPreferredHeight() {
+        return mTimeBarHeight;
+    }
+
+    @Override
+    public void setInfo(String info) {
+        // Do nothing here, show nothing in timeBar's info.
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        if (!isClickable()) {
+            return true;
+        }
+        return super.dispatchTouchEvent(event);
+    }
+
+    public int getTotalTime() {
+        return mTotalTime;
+    }
+
+    public int getCurrentTime() {
+        return mCurrentTime;
+    }
+
+    public boolean seekable() {
+        return mShowScrubber;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/app/TimeLineDataLoader.java b/src/com/android/gallery3d/app/TimeLineDataLoader.java
new file mode 100755
index 0000000..5909103
--- /dev/null
+++ b/src/com/android/gallery3d/app/TimeLineDataLoader.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.app;
+
+import android.os.Handler;
+import android.os.Message;
+import android.os.Process;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.ContentListener;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.ClusterAlbumSet;
+import com.android.gallery3d.ui.SynchronizedHandler;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+public class TimeLineDataLoader {
+    @SuppressWarnings("unused")
+    private static final String TAG = "TimeLineDataLoader";
+    private static final int DATA_CACHE_SIZE = 96 * 2;
+
+    private static final int MSG_LOAD_START = 1;
+    private static final int MSG_LOAD_FINISH = 2;
+    private static final int MSG_RUN_OBJECT = 3;
+
+    private static final int MIN_LOAD_COUNT = 32;
+    private static final int MAX_LOAD_COUNT = 96 * 2;
+
+    private final MediaItem[] mData;
+    private final long[] mItemVersion;
+    private final long[] mSetVersion;
+
+    public static interface DataListener {
+        public void onContentChanged(int index);
+        public void onSizeChanged();
+    }
+
+    private int mActiveStart = 0;
+    private int mActiveEnd = 0;
+
+    private int mContentStart = 0;
+    private int mContentEnd = 0;
+
+    private final MediaSet mSource;
+    private long mSourceVersion = MediaObject.INVALID_DATA_VERSION;
+
+    private final Handler mMainHandler;
+    private int mSize = 0;
+
+    private ArrayList<DataListener> mDataListener = new ArrayList<>();
+    private MySourceListener mSourceListener = new MySourceListener();
+    private LoadingListener mLoadingListener;
+
+    private ReloadTask mReloadTask;
+    // the data version on which last loading failed
+    private long mFailedVersion = MediaObject.INVALID_DATA_VERSION;
+
+    public TimeLineDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) {
+        mSource = mediaSet;
+        mData = new MediaItem[DATA_CACHE_SIZE];
+        mItemVersion = new long[DATA_CACHE_SIZE];
+        mSetVersion = new long[DATA_CACHE_SIZE];
+        Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION);
+        Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION);
+
+        mMainHandler = new SynchronizedHandler(context.getGLRoot()) {
+            @Override
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case MSG_RUN_OBJECT:
+                        ((Runnable) message.obj).run();
+                        return;
+                    case MSG_LOAD_START:
+                        if (mLoadingListener != null) mLoadingListener.onLoadingStarted();
+                        return;
+                    case MSG_LOAD_FINISH:
+                        if (mLoadingListener != null) {
+                            boolean loadingFailed =
+                                    (mFailedVersion != MediaObject.INVALID_DATA_VERSION);
+                            mLoadingListener.onLoadingFinished(loadingFailed);
+                        }
+                        return;
+                }
+            }
+        };
+    }
+
+    public void resume() {
+        mSource.addContentListener(mSourceListener);
+        mReloadTask = new ReloadTask();
+        mReloadTask.start();
+    }
+
+    public void pause() {
+        mReloadTask.terminate();
+        mReloadTask = null;
+        mSource.removeContentListener(mSourceListener);
+    }
+
+    public MediaSet getMediaSet(int index) {
+        return ((ClusterAlbumSet) mSource).getAlbumFromindex(index);
+    }
+
+    public MediaItem get(int index) {
+        if (!isActive(index)) {
+            ArrayList<MediaItem> items = mSource.getMediaItem(index, 1);
+            if (items != null && items.size() > 0) {
+                return items.get(0);
+            }
+        }
+        return mData[index % mData.length];
+    }
+
+    public int getTimeLineTitlesCount() {
+        return mSource.getSubMediaSetCount();
+    }
+
+    public boolean isActive(int index) {
+        return index >= mActiveStart && index < mActiveEnd;
+    }
+
+    public int size() {
+        return mSize;
+    }
+
+    public int[] getSubMediaSetCount() {
+        ClusterAlbumSet set = (ClusterAlbumSet) mSource;
+        int albumCount = set.getSubMediaSetCount();
+        int[] counts = new int[albumCount];
+        for (int i = albumCount - 1; i >= 0; --i) {
+            counts[i] = set.getSubMediaSet(i).getSelectableItemCount();
+        }
+        return counts;
+    }
+
+    // Returns the index of the MediaItem with the given path or
+    // -1 if the path is not cached
+    public int findItem(Path id) {
+        return getIndex(id, true);
+    }
+
+    /**
+     * @param id            given path
+     * @param needTitleItem timeline title items will be filtered out if true.
+     * @return the index of the MediaItem with the given path or -1 if the path is not cached.
+     */
+    public int getIndex(Path id, final boolean needTitleItem) {
+        for (int i = mContentStart, offset = 0; i < mContentEnd; i++) {
+            MediaItem item = mData[i % DATA_CACHE_SIZE];
+            if (item != null) {
+                if (!needTitleItem && !item.isSelectable()) {
+                    offset++;
+                } else if (id == item.getPath()) {
+                    return i - offset;
+                }
+            }
+        }
+        return -1;
+    }
+
+    private void clearSlot(int slotIndex) {
+        mData[slotIndex] = null;
+        mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
+        mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION;
+    }
+
+    private void setContentWindow(int contentStart, int contentEnd) {
+        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
+        int end = mContentEnd;
+        int start = mContentStart;
+
+        // We need change the content window before calling reloadData(...)
+        synchronized (this) {
+            mContentStart = contentStart;
+            mContentEnd = contentEnd;
+        }
+        if (contentStart >= end || start >= contentEnd) {
+            for (int i = start, n = end; i < n; ++i) {
+                clearSlot(i % DATA_CACHE_SIZE);
+            }
+        } else {
+            for (int i = start; i < contentStart; ++i) {
+                clearSlot(i % DATA_CACHE_SIZE);
+            }
+            for (int i = contentEnd, n = end; i < n; ++i) {
+                clearSlot(i % DATA_CACHE_SIZE);
+            }
+        }
+        if (mReloadTask != null) mReloadTask.notifyDirty();
+    }
+
+    public void setActiveWindow(int start, int end) {
+        if (start == mActiveStart && end == mActiveEnd) return;
+
+        Utils.assertTrue(start <= end
+                && end - start <= mData.length && end <= mSize);
+
+        int length = mData.length;
+        mActiveStart = start;
+        mActiveEnd = end;
+
+        // If no data is visible, keep the cache content
+        if (start == end) return;
+
+        int contentStart = Utils.clamp((start + end) / 2 - length / 2,
+                0, Math.max(0, mSize - length));
+        int contentEnd = Math.min(contentStart + length, mSize);
+        if (mContentStart > start || mContentEnd < end
+                || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) {
+            setContentWindow(contentStart, contentEnd);
+        }
+    }
+
+    private class MySourceListener implements ContentListener {
+        @Override
+        public void onContentDirty() {
+            if (mReloadTask != null) mReloadTask.notifyDirty();
+        }
+    }
+
+    public void setDataListener(DataListener listener) {
+        mDataListener.add(listener);
+    }
+
+    public void removeDataListener(DataListener listener) {
+        mDataListener.remove(listener);
+    }
+
+    public void setLoadingListener(LoadingListener listener) {
+        mLoadingListener = listener;
+    }
+
+    private <T> T executeAndWait(Callable<T> callable) {
+        FutureTask<T> task = new FutureTask<T>(callable);
+        mMainHandler.sendMessage(
+                mMainHandler.obtainMessage(MSG_RUN_OBJECT, task));
+        try {
+            return task.get();
+        } catch (InterruptedException e) {
+            return null;
+        } catch (ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static class UpdateInfo {
+        public long version;
+        public int reloadStart;
+        public int reloadCount;
+
+        public int size;
+        public ArrayList<MediaItem> items;
+    }
+
+    private class GetUpdateInfo implements Callable<UpdateInfo> {
+        private final long mVersion;
+
+        public GetUpdateInfo(long version) {
+            mVersion = version;
+        }
+
+        @Override
+        public UpdateInfo call() throws Exception {
+            if (mFailedVersion == mVersion) {
+                // previous loading failed, return null to pause loading
+                return null;
+            }
+            UpdateInfo info = new UpdateInfo();
+            long version = mVersion;
+            info.version = mSourceVersion;
+            info.size = mSize;
+            long setVersion[] = mSetVersion;
+            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
+                int index = i % DATA_CACHE_SIZE;
+                if (setVersion[index] != version) {
+                    info.reloadStart = i;
+                    info.reloadCount = Math.min(MAX_LOAD_COUNT, n - i);
+                    return info;
+                }
+            }
+            return mSourceVersion == mVersion ? null : info;
+        }
+    }
+
+    private class UpdateContent implements Callable<Void> {
+
+        private UpdateInfo mUpdateInfo;
+
+        public UpdateContent(UpdateInfo info) {
+            mUpdateInfo = info;
+        }
+
+        @Override
+        public Void call() throws Exception {
+            UpdateInfo info = mUpdateInfo;
+            mSourceVersion = info.version;
+            if (mSize != info.size) {
+                mSize = info.size;
+                if (mDataListener != null)
+                    for (DataListener l : mDataListener) {
+                        l.onSizeChanged();
+                    }
+                if (mContentEnd > mSize) mContentEnd = mSize;
+                if (mActiveEnd > mSize) mActiveEnd = mSize;
+            }
+
+            ArrayList<MediaItem> items = info.items;
+
+            mFailedVersion = MediaObject.INVALID_DATA_VERSION;
+            if ((items == null) || items.isEmpty()) {
+                if (info.reloadCount > 0) {
+                    mFailedVersion = info.version;
+                    Log.d(TAG, "loading failed: " + mFailedVersion);
+                }
+                return null;
+            }
+            int start = Math.max(info.reloadStart, mContentStart);
+            int end = Math.min(info.reloadStart + items.size(), mContentEnd);
+
+            for (int i = start; i < end; ++i) {
+                int index = i % DATA_CACHE_SIZE;
+                mSetVersion[index] = info.version;
+                MediaItem updateItem = items.get(i - info.reloadStart);
+                if (updateItem != null) {
+                    long itemVersion = updateItem.getDataVersion();
+                    if (mItemVersion[index] != itemVersion) {
+                        mItemVersion[index] = itemVersion;
+                        mData[index] = updateItem;
+                        if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) {
+                            for (DataListener l : mDataListener) {
+                                l.onContentChanged(i);
+                            }
+                        }
+                    }
+               }
+            }
+            return null;
+        }
+    }
+
+    /*
+     * The thread model of ReloadTask
+     *      *
+     * [Reload Task]       [Main Thread]
+     *       |                   |
+     * getUpdateInfo() -->       |           (synchronous call)
+     *     (wait) <----    getUpdateInfo()
+     *       |                   |
+     *   Load Data               |
+     *       |                   |
+     * updateContent() -->       |           (synchronous call)
+     *     (wait)          updateContent()
+     *       |                   |
+     *       |                   |
+     */
+    private class ReloadTask extends Thread {
+
+        private volatile boolean mActive = true;
+        private volatile boolean mDirty = true;
+        private boolean mIsLoading = false;
+
+        private void updateLoading(boolean loading) {
+            if (mIsLoading == loading) return;
+            mIsLoading = loading;
+            mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH);
+        }
+
+        @Override
+        public void run() {
+            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            boolean updateComplete = false;
+            long version = MediaObject.INVALID_DATA_VERSION;
+            while (mActive) {
+                synchronized (this) {
+                    if (mActive && !mDirty && updateComplete
+                            && version != MediaObject.INVALID_DATA_VERSION) {
+                        updateLoading(false);
+                        Utils.waitWithoutInterrupt(this);
+                        continue;
+                    }
+                    mDirty = false;
+                }
+                updateLoading(true);
+                version = mSource.reload();
+                UpdateInfo info = executeAndWait(new GetUpdateInfo(version));
+                updateComplete = info == null;
+                if (updateComplete) {
+                    continue;
+                }
+                if (info.version != version) {
+                    info.size = mSource.getMediaItemCount();
+                    info.version = version;
+                }
+                if (info.reloadCount > 0) {
+                    int start = Math.max(info.reloadStart, mContentStart);
+                    int end = Math.min(info.reloadStart + info.reloadCount, mContentEnd);
+                    info.items = mSource.getMediaItem(start, end - start);
+                }
+                executeAndWait(new UpdateContent(info));
+            }
+            updateLoading(false);
+        }
+
+        public synchronized void notifyDirty() {
+            mDirty = true;
+            notifyAll();
+        }
+
+        public synchronized void terminate() {
+            mActive = false;
+            notifyAll();
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/TimeLinePage.java b/src/com/android/gallery3d/app/TimeLinePage.java
new file mode 100755
index 0000000..a9abc81
--- /dev/null
+++ b/src/com/android/gallery3d/app/TimeLinePage.java
@@ -0,0 +1,898 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.MediaStore;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.ClusterAlbum;
+import com.android.gallery3d.data.DataManager;
+import com.android.gallery3d.data.MediaDetails;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.ClusterAlbumSet;
+import com.android.gallery3d.filtershow.crop.CropActivity;
+import com.android.gallery3d.filtershow.crop.CropExtras;
+import com.android.gallery3d.glrenderer.FadeTexture;
+import com.android.gallery3d.glrenderer.GLCanvas;
+import com.android.gallery3d.ui.ActionModeHandler;
+import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener;
+import com.android.gallery3d.ui.DetailsHelper;
+import com.android.gallery3d.ui.DetailsHelper.CloseListener;
+import com.android.gallery3d.ui.GLRoot;
+import com.android.gallery3d.ui.GLView;
+import com.android.gallery3d.ui.PhotoFallbackEffect;
+import com.android.gallery3d.ui.RelativePosition;
+import com.android.gallery3d.ui.SelectionManager;
+import com.android.gallery3d.ui.SynchronizedHandler;
+import com.android.gallery3d.ui.TimeLineSlotRenderer;
+import com.android.gallery3d.ui.TimeLineSlotView;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.GalleryUtils;
+import org.codeaurora.gallery.R;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class TimeLinePage extends ActivityState implements
+        GalleryActionBar.ClusterRunner, SelectionManager.SelectionListener,
+        MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener {
+
+    private static final String TAG = "TimeLinePage";
+
+    public static final String KEY_MEDIA_PATH = "media-path";
+    public static final String KEY_AUTO_SELECT_ALL = "auto-select-all";
+    public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu";
+    public static final String KEY_RESUME_ANIMATION = "resume_animation";
+
+    private static final int REQUEST_SLIDESHOW = 1;
+    public static final int REQUEST_PHOTO = 2;
+    private static final int REQUEST_DO_ANIMATION = 3;
+
+    private static final int BIT_LOADING_RELOAD = 1;
+    private static final int BIT_LOADING_SYNC = 2;
+
+    private static final float USER_DISTANCE_METER = 0.3f;
+
+    private boolean mIsActive = false;
+    private TimeLineSlotRenderer mAlbumView;
+    private Path mMediaSetPath;
+    private TimeLineSlotView mSlotView;
+    private TimeLineDataLoader mAlbumDataAdapter;
+    protected SelectionManager mSelectionManager;
+    private boolean mGetContent;
+    private boolean mShowClusterMenu;
+
+    protected ActionModeHandler mActionModeHandler;
+    private int mFocusIndex = 0;
+    private DetailsHelper mDetailsHelper;
+    private MyDetailsSource mDetailsSource;
+    private MediaSet mMediaSet;
+    private boolean mShowDetails;
+    private float mUserDistance; // in pixel
+    private Future<Integer> mSyncTask = null;
+    private boolean mLaunchedFromPhotoPage;
+    private boolean mInCameraApp;
+    private TextView tvEmptyAlbum;
+
+    private int mLoadingBits = 0;
+    private boolean mInitialSynced = false;
+    private int mSyncResult;
+    private boolean mLoadingFailed;
+    private RelativePosition mOpenCenter = new RelativePosition();
+
+    private Handler mHandler;
+    private static final int MSG_PICK_PHOTO = 0;
+
+    private PhotoFallbackEffect mResumeEffect;
+    private PhotoFallbackEffect.PositionProvider mPositionProvider =
+            new PhotoFallbackEffect.PositionProvider() {
+                @Override
+                public Rect getPosition(int index) {
+                    Rect rect = mSlotView.getSlotRect(index);
+                    Rect bounds = mSlotView.bounds();
+                    rect.offset(bounds.left - mSlotView.getScrollX(),
+                            bounds.top - mSlotView.getScrollY());
+                    return rect;
+                }
+
+                @Override
+                public int getItemIndex(Path path) {
+                    int start = mSlotView.getVisibleStart();
+                    int end = mSlotView.getVisibleEnd();
+                    for (int i = start; i < end; ++i) {
+                        MediaItem item = mAlbumDataAdapter.get(i);
+                        if (item != null && item.getPath() == path) return i;
+                    }
+                    return -1;
+                }
+            };
+
+    private Button mCameraButton;
+    private boolean mShowedEmptyToastForSelf = false;
+
+
+    @Override
+    protected int getBackgroundColorId() {
+        return R.color.album_background;
+    }
+
+    private final GLView mRootPane = new GLView() {
+        private final float mMatrix[] = new float[16];
+
+        @Override
+        protected void onLayout(
+                boolean changed, int left, int top, int right, int bottom) {
+
+            int slotViewTop;
+            android.widget.Toolbar toolbar = mActivity.getToolbar();
+            if (toolbar != null) {
+                slotViewTop = toolbar.getLayoutParams().height;
+            } else {
+                slotViewTop = mActivity.getGalleryActionBar().getHeight();
+            }
+            int padding =0 ;
+            if((right - left) > (bottom - top)) {
+                padding =  (int) mActivity.getResources().getDimension(R.dimen.timeline_land_margin);
+            } else {
+                padding = (int) mActivity.getResources().getDimension(R.dimen.timeline_port_margin);
+            }
+            int slotViewBottom = bottom - top;
+            int slotViewRight = right - left - padding;
+
+            if (mShowDetails) {
+                mDetailsHelper.layout(left, slotViewTop, right, bottom);
+            } else {
+                mAlbumView.setHighlightItemPath(null);
+            }
+
+            // Set the mSlotView as a reference point to the open animation
+            mOpenCenter.setReferencePosition(0, slotViewTop);
+            mSlotView.layout(padding, slotViewTop, slotViewRight, slotViewBottom);
+            GalleryUtils.setViewPointMatrix(mMatrix,
+                    (right - left) / 2, (bottom - top) / 2, -mUserDistance);
+        }
+
+        @Override
+        protected void render(GLCanvas canvas) {
+            canvas.save(GLCanvas.SAVE_FLAG_MATRIX);
+            canvas.multiplyMatrix(mMatrix, 0);
+            super.render(canvas);
+
+            if (mResumeEffect != null) {
+                boolean more = mResumeEffect.draw(canvas);
+                if (!more) {
+                    mResumeEffect = null;
+                    mAlbumView.setSlotFilter(null);
+                }
+                // We want to render one more time even when no more effect
+                // required. So that the animated thumbnails could be draw
+                // with declarations in super.render().
+                invalidate();
+            }
+            canvas.restore();
+        }
+    };
+
+    // This are the transitions we want:
+    //
+    // +--------+           +------------+    +-------+    +----------+
+    // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet |
+    // |  View  | thumbnail |   Photo    | up | Page  | up |   Page   |
+    // +--------+           +------------+    +-------+    +----------+
+    //     ^                      |               |            ^  |
+    //     |                      |               |            |  |         close
+    //     +----------back--------+               +----back----+  +--back->  app
+    //
+    @Override
+    protected void onBackPressed() {
+        if (mShowDetails) {
+            hideDetails();
+        } else if (mSelectionManager.inSelectionMode()) {
+            mSelectionManager.leaveSelectionMode();
+        } else {
+            if(mLaunchedFromPhotoPage) {
+            mActivity.getTransitionStore().putIfNotPresent(
+                    PhotoPage.KEY_ALBUMPAGE_TRANSITION,
+                    PhotoPage.MSG_ALBUMPAGE_RESUMED);
+            }
+            if (mInCameraApp) {
+                super.onBackPressed();
+            } else {
+                onUpPressed();
+            }
+        }
+    }
+
+    private void onUpPressed() {
+        if (mInCameraApp) {
+            GalleryUtils.startGalleryActivity(mActivity);
+        } else
+            super.onBackPressed();
+    }
+
+    private void onDown(int index) {
+        mAlbumView.setPressedIndex(index);
+    }
+
+    private void onUp(boolean followedByLongPress) {
+        if (followedByLongPress) {
+            // Avoid showing press-up animations for long-press.
+            mAlbumView.setPressedIndex(-1);
+        } else {
+            mAlbumView.setPressedUp();
+        }
+    }
+
+    private void onSingleTapUp(int slotIndex , boolean isTitle) {
+        if (!mIsActive) return;
+            if (mSelectionManager.inSelectionMode()) {
+                if(isTitle){
+                    MediaSet targetSet = mAlbumDataAdapter.getMediaSet(slotIndex);
+                    if (targetSet == null) return;
+                    ArrayList<Path> paths = ((ClusterAlbum)targetSet).getMediaItems();
+                    if (paths == null || paths.size() <= 0) return;
+                    mSelectionManager.toggleTimeLineSet(paths);
+                    mSlotView.invalidate();
+                } else {
+                    MediaItem item = mAlbumDataAdapter.get(slotIndex);
+                    if (item == null) return; // Item not ready yet, ignore the click
+                    if (mSelectionManager.getSelectedCount() > 0) {
+                        if (!ActionModeHandler.isThreadComplete)
+                            return;
+                    }
+                    mSelectionManager.toggle(item.getPath());
+                    mSlotView.invalidate();
+                }
+            } else if(!isTitle){
+                // Render transition in pressed state
+                mAlbumView.setPressedIndex(slotIndex);
+                mAlbumView.setPressedUp();
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0),
+                        FadeTexture.DURATION);
+            }
+    }
+
+    private void pickPhoto(int slotIndex) {
+        pickPhoto(slotIndex, false);
+    }
+
+    private void pickPhoto(int slotIndex, boolean startInFilmstrip) {
+        if (!mIsActive) return;
+
+        if (!startInFilmstrip) {
+            // Launch photos in lights out mode
+            mActivity.getGLRoot().setLightsOutMode(true);
+        }
+
+        MediaItem item = mAlbumDataAdapter.get(slotIndex);
+
+        if (mGetContent) {
+            if (item == null)
+                return; // Item not ready yet, ignore the click
+            onGetContent(item);
+        } else if (mLaunchedFromPhotoPage) {
+            TransitionStore transitions = mActivity.getTransitionStore();
+            transitions.put(
+                    PhotoPage.KEY_ALBUMPAGE_TRANSITION,
+                    PhotoPage.MSG_ALBUMPAGE_PICKED);
+            transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
+            onBackPressed();
+        } else {
+            MediaSet targetset = mAlbumDataAdapter.getMediaSet(slotIndex);
+            if (targetset == null || item == null) return;
+
+            Bundle data = new Bundle();
+            data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex-1);
+            data.putString(PhotoPage.KEY_MEDIA_SET_PATH,
+                    targetset.getPath().toString());
+            data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT,
+                    mSlotView.getSlotRect(slotIndex, mRootPane));
+            data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH,
+                    item.getPath().toString());
+            data.putBoolean(PhotoPage.KEY_FROM_TIMELINE_SCREEN, true);
+            data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION,
+                    PhotoPage.MSG_ALBUMPAGE_STARTED);
+            data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP,
+                    startInFilmstrip);
+            data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetset.isCameraRoll());
+            mActivity.getStateManager().startStateForResult(
+                    SinglePhotoPage.class, REQUEST_PHOTO, data);
+        }
+    }
+
+    private void onGetContent(final MediaItem item) {
+        DataManager dm = mActivity.getDataManager();
+        Activity activity = mActivity;
+        if (mData.getString(GalleryActivity.EXTRA_CROP) != null) {
+            Uri uri = dm.getContentUri(item.getPath());
+            Intent intent = new Intent(CropActivity.CROP_ACTION, uri)
+                    .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
+                    .putExtras(getData());
+            if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) {
+                intent.putExtra(CropExtras.KEY_RETURN_DATA, true);
+            }
+            activity.startActivity(intent);
+            activity.finish();
+        } else {
+            Intent intent = new Intent(null, item.getContentUri())
+                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+            activity.setResult(Activity.RESULT_OK, intent);
+            activity.finish();
+        }
+    }
+
+    public void onLongTap(int slotIndex, boolean isTitle) {
+        if (mGetContent) return;
+        if(isTitle){
+            MediaSet targetSet = mAlbumDataAdapter.getMediaSet(slotIndex);
+            if (targetSet == null) return;
+            ArrayList<Path> paths = ((ClusterAlbum)targetSet).getMediaItems();
+            if (paths == null || paths.size() <= 0) return;
+            mSelectionManager.setAutoLeaveSelectionMode(true);
+            mSelectionManager.toggleTimeLineSet(paths);
+            mSlotView.invalidate();
+        } else {
+            MediaItem item = mAlbumDataAdapter.get(slotIndex);
+            if (item == null) return;
+            mSelectionManager.setAutoLeaveSelectionMode(true);
+            mSelectionManager.toggle(item.getPath());
+            mSlotView.invalidate();
+        }
+    }
+
+    @Override
+    public void doCluster(int clusterType) {
+        String basePath = mMediaSet.getPath().toString();
+        String newPath = FilterUtils.newClusterPath(basePath, clusterType);
+        Bundle data = new Bundle(getData());
+        data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath);
+        if (mShowClusterMenu) {
+            Context context = mActivity.getAndroidContext();
+            data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName());
+            data.putString(AlbumSetPage.KEY_SET_SUBTITLE,
+                    GalleryActionBar.getClusterByTypeString(context, clusterType));
+        }
+
+        mActivity.getStateManager().startStateForResult(
+                AlbumSetPage.class, REQUEST_DO_ANIMATION, data);
+    }
+
+    @Override
+    protected void onCreate(Bundle data, Bundle restoreState) {
+        super.onCreate(data, restoreState);
+        mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER);
+        initializeViews();
+        initializeData(data);
+        mGetContent = data.getBoolean(GalleryActivity.KEY_GET_CONTENT, false);
+        mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false);
+        mDetailsSource = new MyDetailsSource();
+
+        if (data.getBoolean(KEY_AUTO_SELECT_ALL)) {
+            mSelectionManager.selectAll();
+        }
+
+        mLaunchedFromPhotoPage =
+                mActivity.getStateManager().hasStateClass(FilmstripPage.class);
+        mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false);
+
+        mHandler = new SynchronizedHandler(mActivity.getGLRoot()) {
+            @Override
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case MSG_PICK_PHOTO: {
+                        pickPhoto(message.arg1);
+                        break;
+                    }
+                    default:
+                        throw new AssertionError(message.what);
+                }
+            }
+        };
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        mIsActive = true;
+
+        mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION);
+        if (mResumeEffect != null) {
+            mAlbumView.setSlotFilter(mResumeEffect);
+            mResumeEffect.setPositionProvider(mPositionProvider);
+            mResumeEffect.start();
+        }
+
+        setContentPane(mRootPane);
+
+        // Set the reload bit here to prevent it exit this page in clearLoadingBit().
+        setLoadingBit(BIT_LOADING_RELOAD);
+        if (null != mMediaSet) {
+            //set to show timeline title
+            mMediaSet.setShowAlbumsetTimeTitle(true);
+        }
+        mLoadingFailed = false;
+        mAlbumDataAdapter.resume();
+
+        mAlbumView.resume();
+        mAlbumView.setPressedIndex(-1);
+        mActionModeHandler.resume();
+        if (!mInitialSynced) {
+            setLoadingBit(BIT_LOADING_SYNC);
+            mSyncTask = mMediaSet.requestSync(this);
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mIsActive = false;
+
+        mAlbumView.setSlotFilter(null);
+        mActionModeHandler.pause();
+        mAlbumDataAdapter.pause();
+        mAlbumView.pause();
+        DetailsHelper.pause();
+        /*if (!mGetContent) {
+            mActivity.getGalleryActionBar().disableAlbumModeMenu(true);
+        }*/
+
+        if (mSyncTask != null) {
+            mSyncTask.cancel();
+            mSyncTask = null;
+            clearLoadingBit(BIT_LOADING_SYNC);
+        }
+
+        hideEmptyAlbumToast();
+        hideCameraButton();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mAlbumDataAdapter != null) {
+            mAlbumDataAdapter.setLoadingListener(null);
+        }
+        mActionModeHandler.destroy();
+    }
+
+    private void initializeViews() {
+        mSelectionManager = new SelectionManager(mActivity, false);
+        mSelectionManager.setSelectionListener(this);
+        Config.TimeLinePage config = Config.TimeLinePage.get(mActivity);
+        mSlotView = new TimeLineSlotView(mActivity, config.slotViewSpec);
+        mAlbumView = new TimeLineSlotRenderer(mActivity, mSlotView,
+                mSelectionManager, config.labelSpec, config.placeholderColor);
+        mSlotView.setSlotRenderer(mAlbumView);
+        mRootPane.addComponent(mSlotView);
+        mSlotView.setListener(new TimeLineSlotView.SimpleListener() {
+            @Override
+            public void onDown(int index) {
+                TimeLinePage.this.onDown(index);
+            }
+
+            @Override
+            public void onUp(boolean followedByLongPress) {
+                TimeLinePage.this.onUp(followedByLongPress);
+            }
+
+            @Override
+            public void onSingleTapUp(int slotIndex, boolean isTitle) {
+                TimeLinePage.this.onSingleTapUp(slotIndex, isTitle);
+            }
+
+            @Override
+            public void onLongTap(int slotIndex, boolean isTitle) {
+                TimeLinePage.this.onLongTap(slotIndex, isTitle);
+            }
+        });
+        mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager);
+        mActionModeHandler.setActionModeListener(new ActionModeListener() {
+            @Override
+            public boolean onActionItemClicked(MenuItem item) {
+                return onItemSelected(item);
+            }
+        });
+    }
+
+    private void initializeData(Bundle data) {
+        mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH));
+        mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath);
+        if (mMediaSet == null) {
+            Utils.fail("MediaSet is null. Path = %s", mMediaSetPath);
+        }
+        mAlbumDataAdapter = new TimeLineDataLoader(mActivity, mMediaSet);
+        mSelectionManager.setSourceMediaSet(mMediaSet);
+        mSelectionManager.setTimeLineDataLoader(mAlbumDataAdapter);
+        //mSelectionManager.setAlbumDataAdapter(mAlbumDataAdapter);
+        mAlbumDataAdapter.setLoadingListener(new MyLoadingListener());
+        mAlbumView.setModel(mAlbumDataAdapter);
+    }
+
+    private void showDetails() {
+        mShowDetails = true;
+        if (mDetailsHelper == null) {
+            mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource);
+            mDetailsHelper.setCloseListener(new CloseListener() {
+                @Override
+                public void onClose() {
+                    hideDetails();
+                }
+            });
+        }
+        mDetailsHelper.show();
+    }
+
+    private void hideDetails() {
+        mShowDetails = false;
+        mDetailsHelper.hide();
+        mAlbumView.setHighlightItemPath(null);
+        mSlotView.invalidate();
+    }
+
+    @Override
+    protected boolean onCreateActionBar(Menu menu) {
+        GalleryActionBar actionBar = mActivity.getGalleryActionBar();
+        MenuInflater inflator = getSupportMenuInflater();
+        if (mGetContent) {
+            inflator.inflate(R.menu.pickup, menu);
+            int typeBits = mData.getInt(GalleryActivity.KEY_TYPE_BITS,
+                    DataManager.INCLUDE_IMAGE);
+            actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits));
+        } else {
+            inflator.inflate(R.menu.album, menu);
+            actionBar.setTitle(R.string.timeline_title);
+
+            FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true);
+            //menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu);
+            menu.findItem(R.id.action_camera).setVisible(GalleryUtils.isAnyCameraAvailable(mActivity));
+            menu.findItem(R.id.action_view_type).setVisible(false);
+        }
+
+        return true;
+    }
+
+    private void prepareAnimationBackToFilmstrip(int slotIndex) {
+        if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return;
+        MediaItem item = mAlbumDataAdapter.get(slotIndex);
+        if (item == null) return;
+        TransitionStore transitions = mActivity.getTransitionStore();
+        transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex);
+        transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT,
+                mSlotView.getSlotRect(slotIndex, mRootPane));
+    }
+
+    private void switchToFilmstrip() {
+        // Invalid album, return back directly.
+        if (mAlbumDataAdapter.size() < 1) {
+            return;
+        }
+
+        int targetPhoto = mSlotView.getVisibleStart();
+        if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                .getLayoutDirectionFromLocale(Locale.getDefault())) {
+            // Fetch corresponding index from another side, only in RTL
+            targetPhoto = mAlbumDataAdapter.size() - targetPhoto - 1;
+        }
+        prepareAnimationBackToFilmstrip(targetPhoto);
+        if(mLaunchedFromPhotoPage) {
+            onBackPressed();
+        } else {
+            pickPhoto(targetPhoto, true);
+        }
+    }
+
+    @Override
+    protected boolean onItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home: {
+                onUpPressed();
+                return true;
+            }
+            case R.id.action_cancel:
+                mActivity.getStateManager().finishState(this);
+                return true;
+            case R.id.action_select:
+                mSelectionManager.setAutoLeaveSelectionMode(true);
+                mSelectionManager.enterSelectionMode();
+                return true;
+            case R.id.action_slideshow: {
+                Bundle data = new Bundle();
+                data.putString(SlideshowPage.KEY_SET_PATH,
+                        mMediaSetPath.toString());
+                data.putBoolean(SlideshowPage.KEY_REPEAT, true);
+                mActivity.getStateManager().startStateForResult(
+                        SlideshowPage.class, REQUEST_SLIDESHOW, data);
+                return true;
+            }
+            case R.id.action_details: {
+                if (mShowDetails) {
+                    hideDetails();
+                } else {
+                    showDetails();
+                }
+                return true;
+            }
+            case R.id.action_camera: {
+                GalleryUtils.startCameraActivity(mActivity);
+                return true;
+            }
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    protected void onStateResult(int request, int result, Intent data) {
+        switch (request) {
+            case REQUEST_SLIDESHOW:
+            {
+                // data could be null, if there is no images in the album
+                if (data == null) return;
+                mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0);
+                mSlotView.setCenterIndex(mFocusIndex);
+                break;
+            }
+            case REQUEST_PHOTO: {
+                if (data == null) return;
+                mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0);
+                mSlotView.makeSlotVisible(mFocusIndex);
+                break;
+            }
+            case REQUEST_DO_ANIMATION: {
+                mSlotView.startRisingAnimation();
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void onSelectionModeChange(int mode) {
+        switch (mode) {
+            case SelectionManager.ENTER_SELECTION_MODE: {
+                mActionModeHandler.startActionMode();
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+                ((GalleryActivity) mActivity).toggleNavBar(false);
+                break;
+            }
+            case SelectionManager.LEAVE_SELECTION_MODE: {
+                mActionModeHandler.finishActionMode();
+                ((GalleryActivity) mActivity).toggleNavBar(true);
+                mRootPane.invalidate();
+                break;
+            }
+            case SelectionManager.SELECT_ALL_MODE: {
+                mActionModeHandler.updateSupportedOperation();
+                mRootPane.invalidate();
+                break;
+            }
+        }
+    }
+
+    @Override
+    public void onSelectionChange(Path path, boolean selected) {
+        int count = mSelectionManager.getSelectedCount();
+        String format = mActivity.getResources().getQuantityString(
+                R.plurals.number_of_items_selected, count);
+        mActionModeHandler.setTitle(String.format(format, count));
+        mActionModeHandler.updateSupportedOperation(path, selected);
+    }
+
+    @Override
+    public void onSyncDone(final MediaSet mediaSet, final int resultCode) {
+        Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result="
+                + resultCode);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                GLRoot root = mActivity.getGLRoot();
+                root.lockRenderThread();
+                mSyncResult = resultCode;
+                try {
+                    if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) {
+                        mInitialSynced = true;
+                    }
+                    clearLoadingBit(BIT_LOADING_SYNC);
+                    showSyncErrorIfNecessary(mLoadingFailed);
+                } finally {
+                    root.unlockRenderThread();
+                }
+            }
+        });
+    }
+
+    // Show sync error toast when all the following conditions are met:
+    // (1) both loading and sync are done,
+    // (2) sync result is error,
+    // (3) the page is still active, and
+    // (4) no photo is shown or loading fails.
+    private void showSyncErrorIfNecessary(boolean loadingFailed) {
+        if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive
+                && (loadingFailed || (mAlbumDataAdapter.size() == 0))) {
+            Toast.makeText(mActivity, R.string.sync_album_error,
+                    Toast.LENGTH_LONG).show();
+        }
+    }
+
+    private void setLoadingBit(int loadTaskBit) {
+        mLoadingBits |= loadTaskBit;
+    }
+
+    private void clearLoadingBit(int loadTaskBit) {
+        mLoadingBits &= ~loadTaskBit;
+        if (mLoadingBits == 0 && mIsActive) {
+            if (mAlbumDataAdapter.size() == 0) {
+                mShowedEmptyToastForSelf = true;
+                showEmptyAlbumToast(Toast.LENGTH_LONG);
+                mSlotView.invalidate();
+            } else {
+                hideEmptyAlbumToast();
+            }
+            return;
+        }
+        // Hide the empty album toast if we are in the root instance of
+        // AlbumSetPage and the album is no longer empty (for instance,
+        // after a sync is completed and web albums have been synced)
+        if (mShowedEmptyToastForSelf) {
+            mShowedEmptyToastForSelf = false;
+            hideEmptyAlbumToast();
+            //hideCameraButton();
+        }
+    }
+
+    private class MyLoadingListener implements LoadingListener {
+        @Override
+        public void onLoadingStarted() {
+            setLoadingBit(BIT_LOADING_RELOAD);
+            mLoadingFailed = false;
+        }
+
+        @Override
+        public void onLoadingFinished(boolean loadingFailed) {
+            clearLoadingBit(BIT_LOADING_RELOAD);
+            mLoadingFailed = loadingFailed;
+            showSyncErrorIfNecessary(loadingFailed);
+        }
+    }
+
+    private class MyDetailsSource implements DetailsHelper.DetailsSource {
+        private int mIndex;
+
+        @Override
+        public int size() {
+            return mAlbumDataAdapter.size() - mAlbumDataAdapter.getTimeLineTitlesCount();
+        }
+
+        @Override
+        public int setIndex() {
+            if (mSelectionManager.getSelected(false) == null) return -1;
+            Path id = mSelectionManager.getSelected(false).get(0);
+            mIndex = mAlbumDataAdapter.findItem(id);
+            int indexToDisplay = mAlbumDataAdapter.getIndex(id, false);
+            return indexToDisplay;
+        }
+
+        @Override
+        public MediaDetails getDetails() {
+            // this relies on setIndex() being called beforehand
+            if (mIndex < 0) return null;
+            MediaObject item = mAlbumDataAdapter.get(mIndex);
+            if (item != null) {
+                mAlbumView.setHighlightItemPath(item.getPath());
+                return item.getDetails();
+            } else {
+                return null;
+            }
+        }
+    }
+
+    @Override
+    public void onAlbumModeSelected(int mode) {
+        if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) {
+            switchToFilmstrip();
+        }
+    }
+
+    private WeakReference<Toast> mEmptyAlbumToast = null;
+
+    private void showCameraButton() {
+        if (mCameraButton == null && !setupCameraButton()) return;
+        mCameraButton.setVisibility(View.VISIBLE);
+    }
+
+    private void hideCameraButton() {
+        if (mCameraButton == null) return;
+        mCameraButton.setVisibility(View.GONE);
+    }
+
+    private boolean setupCameraButton() {
+        if (!GalleryUtils.isAnyCameraAvailable(mActivity)) return false;
+        RelativeLayout galleryRoot = (RelativeLayout)mActivity.findViewById(R.id.gallery_root);
+        if (galleryRoot == null) return false;
+
+        mCameraButton = new Button(mActivity);
+        mCameraButton.setText(R.string.camera_label);
+        mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0);
+        mCameraButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View arg0) {
+                GalleryUtils.startCameraActivity(mActivity);
+            }
+        });
+        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+                RelativeLayout.LayoutParams.WRAP_CONTENT,
+                RelativeLayout.LayoutParams.WRAP_CONTENT);
+        lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+        galleryRoot.addView(mCameraButton, lp);
+        return true;
+    }
+
+    private void showEmptyAlbumToast(int toastLength) {
+        RelativeLayout galleryRoot = (RelativeLayout) mActivity.findViewById(R.id.gallery_root);
+        if (galleryRoot == null) return;
+        if (tvEmptyAlbum == null) {
+            tvEmptyAlbum = new TextView(mActivity);
+            tvEmptyAlbum.setText(R.string.tvEmptyAlbum);
+            tvEmptyAlbum.setTextColor(Color.parseColor("#8A000000"));
+            tvEmptyAlbum.setGravity(Gravity.CENTER);
+            tvEmptyAlbum.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);
+            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
+                    RelativeLayout.LayoutParams.WRAP_CONTENT,
+                    RelativeLayout.LayoutParams.WRAP_CONTENT);
+            lp.addRule(RelativeLayout.CENTER_IN_PARENT);
+            galleryRoot.addView(tvEmptyAlbum, lp);
+        }
+        tvEmptyAlbum.setVisibility(View.VISIBLE);
+    }
+
+    private void hideEmptyAlbumToast() {
+        if (tvEmptyAlbum != null) {
+            tvEmptyAlbum.setVisibility(View.GONE);
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/TrimControllerOverlay.java b/src/com/android/gallery3d/app/TrimControllerOverlay.java
index cae0166..4c90a97 100644
--- a/src/com/android/gallery3d/app/TrimControllerOverlay.java
+++ b/src/com/android/gallery3d/app/TrimControllerOverlay.java
@@ -23,6 +23,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 
 /**
@@ -32,6 +33,7 @@
 
     public TrimControllerOverlay(Context context) {
         super(context);
+        mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol);
     }
 
     @Override
@@ -108,4 +110,14 @@
         }
         return true;
     }
+
+    @Override
+    public void setViewEnabled(boolean isEnabled) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void setPlayPauseReplayResume() {
+        // TODO Auto-generated method stub
+    }
 }
diff --git a/src/com/android/gallery3d/app/TrimTimeBar.java b/src/com/android/gallery3d/app/TrimTimeBar.java
index f8dbc74..6fea3d6 100644
--- a/src/com/android/gallery3d/app/TrimTimeBar.java
+++ b/src/com/android/gallery3d/app/TrimTimeBar.java
@@ -22,7 +22,7 @@
 import android.graphics.Canvas;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 /**
  * The trim time bar view, which includes the current and total time, the progress
@@ -49,6 +49,9 @@
     private int mTrimStartTime;
     private int mTrimEndTime;
 
+    private int mTimeBarMargin;
+    private int mTimeBarTimeMargin;
+
     private final Bitmap mTrimStartScrubber;
     private final Bitmap mTrimEndScrubber;
     public TrimTimeBar(Context context, Listener listener) {
@@ -69,6 +72,9 @@
         // touch padding since we have 3 scrubbers now.
         mScrubberPadding = 0;
         mVPaddingInPx = mVPaddingInPx * 3 / 2;
+        mTimeBarMargin = context.getResources().getDimensionPixelSize(R.dimen.timebar_margin);
+        mTimeBarTimeMargin = context.getResources().
+                getDimensionPixelSize(R.dimen.timebar_time_margin);
     }
 
     private int getBarPosFromTime(int time) {
@@ -77,11 +83,11 @@
     }
 
     private int trimStartScrubberTipOffset() {
-        return mTrimStartScrubber.getWidth() * 3 / 4;
+        return mTrimStartScrubber.getWidth();
     }
 
     private int trimEndScrubberTipOffset() {
-        return mTrimEndScrubber.getWidth() / 4;
+        return 0;
     }
 
     // Based on all the time info (current, total, trimStart, trimEnd), we
@@ -147,9 +153,10 @@
     }
 
     private boolean inScrubber(float x, float y, int startX, int startY, Bitmap scrubber) {
-        int scrubberRight = startX + scrubber.getWidth();
-        int scrubberBottom = startY + scrubber.getHeight();
-        return startX < x && x < scrubberRight && startY < y && y < scrubberBottom;
+        int scrubberRight = startX + scrubber.getWidth() * 2;
+        int scrubberBottom = startY + scrubber.getHeight() * 2;
+        return startX - mScrubberPadding < x && x < scrubberRight + mScrubberPadding
+                && startY - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding;
     }
 
     private int clampScrubber(int scrubberLeft, int offset, int lowerBound, int upperBound) {
@@ -174,14 +181,14 @@
             if (mShowTimes) {
                 margin += mTimeBounds.width();
             }
-            int progressY = h / 4;
-            int scrubberY = progressY - mScrubber.getHeight() / 2 + 1;
-            mScrubberTop = scrubberY;
-            mTrimStartScrubberTop = progressY;
-            mTrimEndScrubberTop = progressY;
+            margin = mLayoutExt.getProgressMargin(margin);
+            int progressY = (h + mScrubberPadding) / 2;
+            mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1;
             mProgressBar.set(
-                    getPaddingLeft() + margin, progressY,
-                    w - getPaddingRight() - margin, progressY + 4);
+                    mTimeBarMargin + margin, progressY,
+                    w - mTimeBarMargin - margin, progressY + 6);
+            mTrimStartScrubberTop = progressY + mProgressBar.height();
+            mTrimEndScrubberTop = progressY + mProgressBar.height();
         }
         update();
     }
@@ -191,18 +198,19 @@
         // draw progress bars
         canvas.drawRect(mProgressBar, mProgressPaint);
         canvas.drawRect(mPlayedBar, mPlayedPaint);
-
         if (mShowTimes) {
-            canvas.drawText(
-                    stringForTime(mCurrentTime),
-                            mTimeBounds.width() / 2 + getPaddingLeft(),
-                            mTimeBounds.height() / 2 +  mTrimStartScrubberTop,
-                    mTimeTextPaint);
-            canvas.drawText(
-                    stringForTime(mTotalTime),
-                            getWidth() - getPaddingRight() - mTimeBounds.width() / 2,
-                            mTimeBounds.height() / 2 +  mTrimStartScrubberTop,
-                    mTimeTextPaint);
+                canvas.drawText(
+                        stringForTime(mCurrentTime),
+                        mTimeBarTimeMargin,
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding -
+                                mLayoutExt.getProgressOffset(mTimeBounds),
+                        mTimeTextPaint);
+                canvas.drawText(
+                        stringForTime(mTotalTime),
+                        getWidth() - mTimeBarTimeMargin,
+                        mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding -
+                                mLayoutExt.getProgressOffset(mTimeBounds),
+                        mTimeTextPaint);
         }
 
         // draw extra scrubbers
@@ -334,6 +342,6 @@
                     break;
             }
         }
-        return false;
+        return true;
     }
 }
diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java
old mode 100644
new mode 100755
index b0ed8e6..527f6cf
--- a/src/com/android/gallery3d/app/TrimVideo.java
+++ b/src/com/android/gallery3d/app/TrimVideo.java
@@ -18,8 +18,10 @@
 
 import android.app.ActionBar;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.app.ProgressDialog;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.media.MediaPlayer;
 import android.net.Uri;
@@ -29,16 +31,19 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.Toast;
 import android.widget.VideoView;
+import androidx.core.content.FileProvider;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.util.SaveVideoFileInfo;
 import com.android.gallery3d.util.SaveVideoFileUtils;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
 
 public class TrimVideo extends Activity implements
         MediaPlayer.OnErrorListener,
@@ -47,7 +52,9 @@
 
     private VideoView mVideoView;
     private TextView mSaveVideoTextView;
+    private ImageView mExitImageView;
     private TrimControllerOverlay mController;
+    private AlertDialog mExitDialog;
     private Context mContext;
     private Uri mUri;
     private final Handler mHandler = new Handler();
@@ -57,6 +64,7 @@
 
     private int mTrimStartTime = 0;
     private int mTrimEndTime = 0;
+    private boolean mCheckTrimStartTime;
     private int mVideoPosition = 0;
     public static final String KEY_TRIM_START = "trim_start";
     public static final String KEY_TRIM_END = "trim_end";
@@ -82,6 +90,33 @@
         actionBar.setDisplayOptions(displayOptions, displayOptions);
         actionBar.setCustomView(R.layout.trim_menu);
 
+        mExitImageView = (ImageView) findViewById(R.id.exit_trim);
+        mExitImageView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mExitDialog = new AlertDialog.Builder(TrimVideo.this,
+                        AlertDialog.THEME_DEVICE_DEFAULT_LIGHT).
+                        setTitle(R.string.trim_video_exit_title).
+                        setMessage(R.string.trim_video_exit_msg).
+                        setPositiveButton(R.string.trim_video_exit_discard,
+                                new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                finish();
+                            }
+                        }).
+                        setNegativeButton(R.string.review_cancel,
+                                new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                dialog.dismiss();
+                            }
+                        }).
+                        create();
+                mExitDialog.show();
+            }
+        });
+
         mSaveVideoTextView = (TextView) findViewById(R.id.start_trim);
         mSaveVideoTextView.setOnClickListener(new View.OnClickListener() {
             @Override
@@ -89,7 +124,7 @@
                 trimVideo();
             }
         });
-        mSaveVideoTextView.setEnabled(false);
+        mSaveVideoTextView.setVisibility(View.GONE);
 
         Intent intent = getIntent();
         mUri = intent.getData();
@@ -177,10 +212,11 @@
         mVideoPosition = mVideoView.getCurrentPosition();
         // If the video position is smaller than the starting point of trimming,
         // correct it.
-        if (mVideoPosition < mTrimStartTime) {
+        if (mCheckTrimStartTime && (mVideoPosition < mTrimStartTime)) {
             mVideoView.seekTo(mTrimStartTime);
             mVideoPosition = mTrimStartTime;
         }
+        mCheckTrimStartTime = false;
         // If the position is bigger than the end point of trimming, show the
         // replay button and pause.
         if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) {
@@ -198,12 +234,13 @@
         }
         mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime);
         // Enable save if there's modifications
-        mSaveVideoTextView.setEnabled(isModified());
+        mSaveVideoTextView.setVisibility(isModified() ? View.VISIBLE : View.GONE);
         return mVideoPosition;
     }
 
     private void playVideo() {
         mVideoView.start();
+        mCheckTrimStartTime = true;
         mController.showPlaying();
         setProgress();
     }
@@ -237,6 +274,7 @@
         new Thread(new Runnable() {
             @Override
             public void run() {
+                boolean hasError = false;
                 try {
                     VideoUtils.startTrim(mSrcFile, mDstFileInfo.mFile,
                             mTrimStartTime, mTrimEndTime);
@@ -244,7 +282,28 @@
                     SaveVideoFileUtils.insertContent(mDstFileInfo,
                             getContentResolver(), mUri);
                 } catch (IOException e) {
+                    hasError = true;
                     e.printStackTrace();
+                } catch (IllegalStateException e) {
+                    hasError = true;
+                    e.printStackTrace();
+                }
+                //If the exception happens,just notify the UI and avoid the crash.
+                if (hasError){
+                    mHandler.post(new Runnable(){
+                        @Override
+                        public void run(){
+                            Toast.makeText(getApplicationContext(),
+                                getString(R.string.fail_trim),
+                                Toast.LENGTH_SHORT)
+                                .show();
+                            if (mProgress != null) {
+                                mProgress.dismiss();
+                                mProgress = null;
+                            }
+                        }
+                    });
+                    return;
                 }
                 // After trimming is done, trigger the UI changed.
                 mHandler.post(new Runnable() {
@@ -261,8 +320,12 @@
                             mProgress = null;
                             // Show the result only when the activity not stopped.
                             Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
-                            intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*");
+                            intent.setDataAndType(
+                                    FileProvider.getUriForFile(mContext,
+                                            "com.android.gallery3d.fileprovider",
+                                            mDstFileInfo.mFile), "video/*");
                             intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false);
+                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                             startActivity(intent);
                             finish();
                         }
@@ -320,6 +383,12 @@
     }
 
     @Override
+    public boolean onIsRTSP() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
     public void onReplay() {
         mVideoView.seekTo(mTrimStartTime);
         playVideo();
diff --git a/src/com/android/gallery3d/app/VideoUtils.java b/src/com/android/gallery3d/app/VideoUtils.java
old mode 100644
new mode 100755
index 359cf76..4f551a6
--- a/src/com/android/gallery3d/app/VideoUtils.java
+++ b/src/com/android/gallery3d/app/VideoUtils.java
@@ -156,11 +156,16 @@
 
             if (selectCurrentTrack) {
                 extractor.selectTrack(i);
-                int dstIndex = muxer.addTrack(format);
-                indexMap.put(i, dstIndex);
-                if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
-                    int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
-                    bufferSize = newSize > bufferSize ? newSize : bufferSize;
+                try {
+                    int dstIndex = muxer.addTrack(format);
+                    indexMap.put(i, dstIndex);
+                    if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+                        int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+                        bufferSize = newSize > bufferSize ? newSize : bufferSize;
+                    }
+                } catch (IllegalArgumentException e) {
+                    Log.e(LOGTAG, "Unsupported format '" + mime + "'");
+                    throw new IOException("Muxer does not support " + mime);
                 }
             }
         }
@@ -221,6 +226,11 @@
         } catch (IllegalStateException e) {
             // Swallow the exception due to malformed source.
             Log.w(LOGTAG, "The source video file is malformed");
+            File f = new File(dstPath);
+            if (f.exists()) {
+                f.delete();
+            }
+            throw e;
         } finally {
             muxer.release();
         }
diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java
index 2022f5a..5c19d90 100644
--- a/src/com/android/gallery3d/app/Wallpaper.java
+++ b/src/com/android/gallery3d/app/Wallpaper.java
@@ -44,6 +44,11 @@
     private static final String IMAGE_TYPE = "image/*";
     private static final String KEY_STATE = "activity-state";
     private static final String KEY_PICKED_ITEM = "picked-item";
+    private static final String KEY_ASPECT_X = "aspectX";
+    private static final String KEY_ASPECT_Y = "aspectY";
+    private static final String KEY_SPOTLIGHT_X = "spotlightX";
+    private static final String KEY_SPOTLIGHT_Y = "spotlightY";
+    private static final String KEY_FROM_SCREENCOLOR = "fromScreenColor";
 
     private static final int STATE_INIT = 0;
     private static final int STATE_PHOTO_PICKED = 1;
@@ -100,7 +105,14 @@
             }
             case STATE_PHOTO_PICKED: {
                 Intent cropAndSetWallpaperIntent;
-                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+                boolean fromScreenColor = false;
+
+                // Do this for screencolor select and crop image to preview.
+                Bundle extras = intent.getExtras();
+                if (extras != null) {
+                    fromScreenColor = extras.getBoolean(KEY_FROM_SCREENCOLOR, false);
+                }
+                if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) && (!fromScreenColor)) {
                     WallpaperManager wpm = WallpaperManager.getInstance(getApplicationContext());
                     try {
                         cropAndSetWallpaperIntent = wpm.getCropAndSetWallpaperIntent(mPickedItem);
@@ -114,11 +126,23 @@
                     }
                 }
 
-                int width = getWallpaperDesiredMinimumWidth();
-                int height = getWallpaperDesiredMinimumHeight();
-                Point size = getDefaultDisplaySize(new Point());
-                float spotlightX = (float) size.x / width;
-                float spotlightY = (float) size.y / height;
+                int width,height;
+                float spotlightX,spotlightY;
+
+                if (fromScreenColor) {
+                    width = extras.getInt(KEY_ASPECT_X, 0);
+                    height = extras.getInt(KEY_ASPECT_Y, 0);
+                    spotlightX = extras.getFloat(KEY_SPOTLIGHT_X, 0);
+                    spotlightY = extras.getFloat(KEY_SPOTLIGHT_Y, 0);
+                } else {
+                    width = getWallpaperDesiredMinimumWidth();
+                    height = getWallpaperDesiredMinimumHeight();
+                    Point size = getDefaultDisplaySize(new Point());
+                    spotlightX = (float) size.x / width;
+                    spotlightY = (float) size.y / height;
+                }
+
+                //Don't set wallpaper from screencolor.
                 cropAndSetWallpaperIntent = new Intent(CropActivity.CROP_ACTION)
                     .setClass(this, CropActivity.class)
                     .setDataAndType(mPickedItem, IMAGE_TYPE)
@@ -131,7 +155,7 @@
                     .putExtra(CropExtras.KEY_SPOTLIGHT_Y, spotlightY)
                     .putExtra(CropExtras.KEY_SCALE, true)
                     .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true)
-                    .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, true);
+                    .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, !fromScreenColor);
                 startActivity(cropAndSetWallpaperIntent);
                 finish();
             }
diff --git a/src/com/android/gallery3d/app/dualcam3d/GLView.java b/src/com/android/gallery3d/app/dualcam3d/GLView.java
new file mode 100644
index 0000000..a98fc6c
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/GLView.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.PointF;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.Surface;
+
+public class GLView extends GLSurfaceView {
+    private static final String TAG = "GLView";
+    private final com.android.gallery3d.app.dualcam3d.gl.Renderer mRenderer;
+
+    private Bitmap mBitmap;
+    private Bitmap mDepthMap;
+    private int mRotation;
+
+    public GLView(Context context) {
+        this(context, null);
+    }
+
+    public GLView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setEGLContextClientVersion(2);
+        mRenderer = new com.android.gallery3d.app.dualcam3d.gl.Renderer();
+        setRenderer(mRenderer);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+        mRenderer.setImageBitmap(mBitmap);
+        mRenderer.setDepthMap(mDepthMap);
+        requestRender();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mRenderer.setImageBitmap(null);
+        mRenderer.setDepthMap(null);
+    }
+
+    public void setImageBitmap(Bitmap bitmap) {
+        mBitmap = bitmap;
+        mRenderer.setImageBitmap(bitmap);
+        mRenderer.setDepthMap(null);
+        requestRender();
+    }
+
+    public void setDepthMap(Bitmap map) {
+        mDepthMap = map;
+        mRenderer.setDepthMap(map);
+        requestRender();
+    }
+
+    public void setOffset(float x, float y) {
+        mRenderer.setOffset(x, y);
+        requestRender();
+    }
+
+    public void setOffsetWithRotation(float x, float y) {
+        if (mRotation == Surface.ROTATION_0 || mRotation == Surface.ROTATION_180) {
+            //noinspection SuspiciousNameCombination
+            setOffset(y, x);
+        } else {
+            setOffset(x, y);
+        }
+    }
+
+    public void setOffsetDelta(float deltaX, float deltaY) {
+        mRenderer.setOffsetDelta(deltaX, deltaY);
+        requestRender();
+    }
+
+    public void recycle() {
+        mListener = null;
+        if (mBitmap != null) {
+            mBitmap.recycle();
+            mBitmap = null;
+        }
+    }
+
+    public void setRotation(int rotation) {
+        mRotation = rotation;
+    }
+
+    private static final float MOVE_THRESHOLD = 1.0f;
+    private PointF mLastPoint;
+    private int mLastAction = MotionEvent.ACTION_DOWN;
+    private Listener mListener;
+
+    public interface Listener {
+        void onMove(float deltaX, float deltaY);
+        void onClick(float x, float y);
+        void onLayout(int width, int height);
+    }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        Matrix invertMatrix = mRenderer.getImageInvertMatrix();
+        if (invertMatrix == null) {
+            return true;
+        }
+
+        float[] point = new float[]{event.getX(), event.getY()};
+        invertMatrix.mapPoints(point);
+
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mLastPoint = new PointF(point[0], point[1]);
+                mLastAction = MotionEvent.ACTION_DOWN;
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (mLastPoint != null) {
+                    float deltaX = point[0] - mLastPoint.x,
+                            deltaY = point[1] - mLastPoint.y;
+                    if (mLastAction == MotionEvent.ACTION_MOVE || (Math.abs(deltaX) > MOVE_THRESHOLD
+                            && Math.abs(deltaY) > MOVE_THRESHOLD)) {
+                        if (mListener != null) {
+                            mListener.onMove(deltaX, deltaY);
+                        }
+                        mLastPoint.set(point[0], point[1]);
+                        mLastAction = MotionEvent.ACTION_MOVE;
+                    }
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mLastAction != MotionEvent.ACTION_MOVE && mListener != null) {
+                    mListener.onClick(point[0], point[1]);
+                }
+                mLastPoint = null;
+                mLastAction = MotionEvent.ACTION_UP;
+                break;
+        }
+        return true;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (changed && mListener != null) {
+            // if the loyout is changed by rotation not by reLayoutGLView,
+            // then save width and heigh of the view for caculating.
+            if (left == 0 && top == 0) {
+                mListener.onLayout(right - left, bottom - top);
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
new file mode 100644
index 0000000..ef5c0ef
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/ThreeDimensionalActivity.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Window;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.threed.Controller;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.util.GDepth;
+
+import org.codeaurora.gallery.R;
+
+public class ThreeDimensionalActivity extends Activity {
+    private static final String TAG = ThreeDimensionalActivity.class.getSimpleName();
+
+    private GLView mImageView;
+    private Controller mController;
+    private LoadImageTask mTask;
+    private int mWidth, mHeight;
+    private int mOrientation;
+    private Bitmap mBitmap = null;
+    private boolean mOriChanged = false;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Log.d(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+        requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.activity_three_dimensional);
+        init();
+        processIntent();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        if (mOrientation != newConfig.orientation) {
+            mOriChanged = true;
+            mOrientation = newConfig.orientation;
+        }
+    }
+
+
+    private void init() {
+        mImageView = (GLView) findViewById(R.id.image);
+        mImageView.setRotation(getWindowManager().getDefaultDisplay().getRotation());
+        mController = new Controller(mImageView, (LinearLayout) findViewById(R.id.mode_3d));
+        mImageView.setListener(new GLView.Listener() {
+            @Override
+            public void onMove(float deltaX, float deltaY) {
+                mController.onMove(deltaX, deltaY);
+            }
+
+            @Override
+            public void onClick(float x, float y) {}
+
+            @Override
+            public void onLayout(int width, int height) {
+                mWidth = width;
+                mHeight = height;
+                reLayoutGLView(false);
+            }
+        });
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mImageView.onResume();
+        mController.start();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mController.stop();
+        mImageView.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        mTask.cancel(true);
+        mTask = null;
+        mBitmap = null;
+        mImageView.recycle();
+        super.onDestroy();
+    }
+
+    private void processIntent() {
+        Intent intent = getIntent();
+        Uri uri = intent.getData();
+        if (uri == null) {
+            finish();
+            return;
+        }
+        mTask = new LoadImageTask();
+        mTask.execute(uri);
+    }
+
+    private void reLayoutGLView(boolean force) {
+        if (!mOriChanged && !force) return;
+        mOriChanged = false;
+        if (mBitmap == null) return;
+        int width = mBitmap.getWidth();
+        int height = mBitmap.getHeight();
+        if (mWidth*height/width > mHeight) {
+            int scaledWidth = width*mHeight/height;
+            int move = (mWidth - scaledWidth)/2;
+            mImageView.layout(move, 0, mWidth-move, mHeight);
+        }
+    }
+
+    private class LoadImageTask extends AsyncTask<Uri, Void, GDepth.Image> {
+        @Override
+        protected GDepth.Image doInBackground(Uri... params) {
+            GDepth.Parser parser = new GDepth.Parser();
+            if (parser.parse(ThreeDimensionalActivity.this, params[0])) {
+                GDepth.Image image = parser.decode();
+                if (image.valid()) {
+                    int orientation = ImageLoader.getMetadataOrientation(
+                            ThreeDimensionalActivity.this, params[0]);
+                    if (orientation != ImageLoader.ORI_NORMAL) {
+                        image.bitmap = ImageLoader.orientBitmap(image.bitmap, orientation);
+                        image.depthMap = ImageLoader.orientBitmap(image.depthMap, orientation);
+                    }
+                    return image;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(GDepth.Image image) {
+            if (!isCancelled()) {
+                if (image != null && image.valid()) {
+                    mImageView.setImageBitmap(image.bitmap);
+                    mImageView.setDepthMap(image.depthMap);
+                    mBitmap = image.bitmap;
+                    reLayoutGLView(true);
+                } else {
+                    finish();
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Error.java b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
new file mode 100644
index 0000000..55f04dd
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Error.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+import android.util.Log;
+
+class Error {
+    private static final String TAG = "GL";
+
+    public static void check() {
+        int error = GLES20.glGetError();
+        if (error != 0) {
+            Throwable t = new Throwable();
+            Log.e(TAG, "error: " + error, t);
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
new file mode 100644
index 0000000..cbc2fa3
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Mesh.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+class Mesh {
+    private static final String TAG = "Mesh";
+
+    private static final float TAN_HALF_FOV =
+            (float) Math.tan(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+
+    public FloatBuffer vertices;
+    public FloatBuffer colors;
+    public FloatBuffer textures;
+    private IntBuffer indices;
+
+    private int indexLength;
+
+    public void render(Shader shader) {
+        if (vertices == null || textures == null || indices == null || indices.capacity() == 0)
+            return;
+        shader.setMesh(this);
+        GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexLength, GLES20.GL_UNSIGNED_INT, indices);
+    }
+
+    private void rewindBuffers() {
+        vertices.position(0);
+        colors.position(0);
+        textures.position(0);
+        indices.position(0);
+    }
+
+    private static ByteBuffer allocateBuffer(int capacity) {
+        ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
+        buffer.order(ByteOrder.nativeOrder());
+        return buffer;
+    }
+
+    public static Mesh create() {
+        Mesh m = new Mesh();
+
+        final int resolutionH = Settings.MESH_RESOLUTION_H;
+        final int resolutionV = Settings.MESH_RESOLUTION_V;
+        final int vertexCount = (resolutionH + 1) * (resolutionV + 1);
+        final int indexCount = resolutionH * resolutionV * 2;
+
+        m.vertices = allocateBuffer(vertexCount * 3 * 4).asFloatBuffer();
+        m.colors = allocateBuffer(vertexCount * 4 * 4).asFloatBuffer();
+        m.textures = allocateBuffer(vertexCount * 2 * 4).asFloatBuffer();
+        m.indices = allocateBuffer(indexCount * 3 * 4).asIntBuffer();
+        m.indexLength = indexCount * 3;
+
+        m.rewindBuffers();
+        return m;
+    }
+
+    private static float getVertexScale(float depth) {
+        return ((depth + Settings.CAMERA_POSITION) * TAN_HALF_FOV);
+    }
+
+    public void update(Bitmap depthMap, int width, int height, float depth) {
+        final int resolutionH = depthMap == null ? 1 : Settings.MESH_RESOLUTION_H;
+        final int resolutionV = depthMap == null ? 1 : Settings.MESH_RESOLUTION_V;
+        indexLength = resolutionH * resolutionV * 2 * 3;
+
+        // / Correct aspect ratio of the rendered image, fit width
+        float scale = getVertexScale(Math.abs(depth));
+        if (depthMap != null) scale *= Settings.ENLARGE_IMAGE;
+        float sizeV = scale * height / width;
+
+        rewindBuffers();
+
+        int[] pixels = null;
+        int depthMapWidth = 0;
+        if (depthMap != null) {
+            depthMapWidth = depthMap.getWidth();
+            int depthMapHeight = depthMap.getHeight();
+            pixels = new int[depthMapWidth * depthMapHeight];
+            depthMap.getPixels(pixels, 0, depthMapWidth, 0, 0, depthMapWidth, depthMapHeight);
+        }
+
+        for (int v = 0; v <= resolutionV; ++v) {
+            float vV = v / (float) resolutionV;
+            float v2 = sizeV - 2 * sizeV * vV;
+            int y = (int) (vV * (height - 1));
+            for (int h = 0; h <= resolutionH; ++h) {
+                float vH = h / (float) resolutionH;
+
+                int depthValue = 0;
+                if (depthMap != null) {
+                    int x = (int) (vH * (width - 1));
+                    depthValue = pixels[y * depthMapWidth + x] >> 24;
+                }
+                vertices.put(-scale + 2 * scale * vH);
+                vertices.put(v2);
+                vertices.put(depthValue * Settings.DEPTH_RATIO);
+
+                colors.put(1f);
+                colors.put(1f);
+                colors.put(1f);
+                colors.put(1f);
+
+                textures.put(vH);
+                textures.put(vV);
+            }
+        }
+
+        for (int v = 0; v < resolutionV; ++v) {
+            for (int h = 0; h < resolutionH; ++h) {
+                int index = v * (resolutionH + 1) + h;
+
+                indices.put(index);
+                indices.put(index + (resolutionH + 1));
+                indices.put(index + 1);
+
+                indices.put(index + (resolutionH + 1));
+                indices.put(index + 1 + (resolutionH + 1));
+                indices.put(index + 1);
+            }
+        }
+        rewindBuffers();
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
new file mode 100644
index 0000000..dedd828
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Renderer.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.graphics.RectF;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.Matrix;
+import android.util.Log;
+
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+public class Renderer implements GLSurfaceView.Renderer {
+    private static final String TAG = "Renderer";
+    public static final float THETA_MAX = (float) Math.toRadians(6);
+    private final float[] mProjectionMatrix = new float[16];
+
+    private float mOffsetX;
+    private float mOffsetY;
+
+    private Bitmap mImageBitmap;
+    private Bitmap mDepthMap;
+
+    private boolean mImageChanged;
+    private boolean mDepthMapChanged;
+
+    private RectF mSurfaceRect;
+    private android.graphics.Matrix mImageInvertMatrix;
+
+    private final Mesh mMesh = Mesh.create();
+    private Shader mShader;
+    private final Texture mImageTexture = new Texture();
+
+    public Renderer() {
+    }
+
+    public void setImageBitmap(Bitmap bitmap) {
+        mImageBitmap = bitmap;
+        mImageChanged = true;
+        mDepthMap = null;
+        mDepthMapChanged = true;
+        setImageInvertMatrix();
+    }
+
+    public void setDepthMap(Bitmap map) {
+        mDepthMap = map;
+        mDepthMapChanged = true;
+        if (map == null) {
+            mOffsetX = 0;
+            mOffsetY = 0;
+        }
+    }
+
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        mShader = new Shader();
+        mShader.bind();
+        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
+        GLES20.glEnable(GLES20.GL_BLEND);
+        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
+    }
+
+    @Override
+    public void onSurfaceChanged(GL10 gl, int width, int height) {
+        Log.d("TAG", "onSurfaceChanged:" + width + "x" + height);
+        float ratio = (float) width / height;
+        float sinY = (float) Math.sin(Math.toRadians(Settings.FIELD_OF_VIEW / 2)) / ratio;
+        float cosY = (float) Math.cos(Math.toRadians(Settings.FIELD_OF_VIEW / 2));
+        float fovY = (float) Math.toDegrees(Math.atan2(sinY, cosY) * 2.f);
+        Matrix.perspectiveM(mProjectionMatrix, 0, fovY, ratio, 0.1f, 500.f);
+        GLES20.glViewport(0, 0, width, height);
+        mSurfaceRect = new RectF(0, 0, width, height);
+        setImageInvertMatrix();
+    }
+
+    private void updateImage() {
+        if (mImageChanged) {
+            mImageTexture.upload(mImageBitmap);
+            mImageTexture.bind();
+            mImageChanged = false;
+        }
+        if (mDepthMapChanged) {
+            int width = mDepthMap == null ? mImageBitmap.getWidth() : mDepthMap.getWidth();
+            int height = mDepthMap == null ? mImageBitmap.getHeight() : mDepthMap.getHeight();
+            mMesh.update(mDepthMap, width, height, Settings.FOREGROUND_POSITION);
+            mDepthMapChanged = false;
+        }
+    }
+
+    private void updateMatrix() {
+        float x = (float) (Math.sin(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+        float y = (float) (Math.sin(mOffsetY)) * Settings.CAMERA_POSITION;
+        float z = (float) (Math.cos(mOffsetX) * Math.cos(mOffsetY)) * Settings.CAMERA_POSITION;
+
+        float[] viewMatrix = new float[16];
+        Matrix.setLookAtM(viewMatrix, 0, x, y, z, 0f, 0f, Settings.FOREGROUND_POSITION,
+                0f, 1f, 0f);
+        float[] matrix = new float[16];
+        Matrix.multiplyMM(matrix, 0, mProjectionMatrix, 0, viewMatrix, 0);
+        mShader.setMatrix(matrix);
+    }
+
+    @Override
+    public void onDrawFrame(GL10 gl) {
+        if (mImageBitmap == null) {
+            return;
+        }
+
+        updateImage();
+        updateMatrix();
+
+        GLES20.glClearColor(0, 0, 0, 0);
+        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
+        mMesh.render(mShader);
+    }
+
+    public void setOffset(float x, float y) {
+        mOffsetX = limit(x);
+        mOffsetY = limit(y);
+    }
+
+    public void setOffsetDelta(float deltaX, float deltaY) {
+        mOffsetX = limit(mOffsetX + deltaX);
+        mOffsetY = limit(mOffsetY + deltaY);
+    }
+
+    private float limit(float theta) {
+        if (theta < -THETA_MAX) return -THETA_MAX;
+        if (theta > THETA_MAX) return THETA_MAX;
+        return theta;
+    }
+
+    public android.graphics.Matrix getImageInvertMatrix() {
+        return mImageInvertMatrix;
+    }
+
+    private void setImageInvertMatrix() {
+        if (mImageBitmap != null && mSurfaceRect != null) {
+            RectF rect = new RectF(0, 0, mImageBitmap.getWidth(), mImageBitmap.getHeight());
+            if (mImageInvertMatrix == null) {
+                mImageInvertMatrix = new android.graphics.Matrix();
+            }
+            android.graphics.Matrix matrix = new android.graphics.Matrix();
+            matrix.setRectToRect(rect, mSurfaceRect, android.graphics.Matrix.ScaleToFit.CENTER);
+            matrix.invert(mImageInvertMatrix);
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
new file mode 100644
index 0000000..5321fdf
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Settings.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+class Settings {
+    // Number of horizontal subdivisions (horizontal resolution)
+    static final int MESH_RESOLUTION_H = 300;
+    // Number of vertical subdivisions (vertical resolution)
+    static final int MESH_RESOLUTION_V = 450;
+    // Field of view of the viewport (horizontal)
+    static final float FIELD_OF_VIEW = 60.0f;
+    // Distance of the viewer from the texture
+    static final float CAMERA_POSITION = 2.75f;
+    // Offset between the background and the foreground
+    static final float FOREGROUND_POSITION = 0.0f;
+
+    static final float ENLARGE_IMAGE = 1.0f;
+
+    // Some hard-coded scalar for now
+    static final float DEPTH_RATIO = 0.003f;
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
new file mode 100644
index 0000000..3641b26
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Shader.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.opengl.GLES20;
+
+class Shader {
+    private static final String vertexShaderCode = //
+            "uniform mat4 uMVPMatrix;" //
+                    + "attribute vec4 vPosition;" //
+                    + "attribute vec2 vTexCoord;" //
+                    + "attribute vec4 vColor;" //
+                    + "varying vec2 texCoord;" //
+                    + "varying vec4 color;" //
+                    + "void main() {" //
+                    + "  gl_Position = uMVPMatrix * vPosition;" //
+                    + "  texCoord = vTexCoord;" //
+                    + "  color = vColor;" //
+                    + "}";
+
+    private static final String fragmentShaderCode = //
+            "precision mediump float;" //
+                    + "uniform vec4 vColor;" //
+                    + "varying vec2 texCoord;" //
+                    + "varying vec4 color;" //
+                    + "uniform sampler2D texSampler2D;" //
+                    + "void main() {" //
+                    + "  gl_FragColor = texture2D(texSampler2D, texCoord);" //
+                    + "  gl_FragColor.w = color.w;" //
+                    + "}";
+
+    private int shaderId = -1;
+
+    public Shader() {
+        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
+        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+
+        shaderId = GLES20.glCreateProgram();
+        Error.check();
+        GLES20.glAttachShader(shaderId, vertexShader);
+        Error.check();
+        GLES20.glAttachShader(shaderId, fragmentShader);
+        Error.check();
+        GLES20.glLinkProgram(shaderId);
+        Error.check();
+    }
+
+    private static int loadShader(int type, String shaderCode) {
+        int shader = GLES20.glCreateShader(type);
+        GLES20.glShaderSource(shader, shaderCode);
+        Error.check();
+        GLES20.glCompileShader(shader);
+        Error.check();
+        return shader;
+    }
+
+    public void bind() {
+        GLES20.glUseProgram(shaderId);
+    }
+
+    public void setMesh(Mesh m) {
+        int vertexHandle = GLES20.glGetAttribLocation(shaderId, "vPosition");
+        GLES20.glEnableVertexAttribArray(vertexHandle);
+        GLES20.glVertexAttribPointer(vertexHandle, 3, GLES20.GL_FLOAT, false, 12, m.vertices);
+
+        int textureHandle = GLES20.glGetAttribLocation(shaderId, "vTexCoord");
+        GLES20.glEnableVertexAttribArray(textureHandle);
+        GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 8, m.textures);
+
+        int colorHandle = GLES20.glGetAttribLocation(shaderId, "vColor");
+        GLES20.glEnableVertexAttribArray(colorHandle);
+        GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, true, 16, m.colors);
+    }
+
+    public void setMatrix(float[] matrix) {
+        int matrixHandle = GLES20.glGetUniformLocation(shaderId, "uMVPMatrix");
+        GLES20.glUniformMatrix4fv(matrixHandle, 1, false, matrix, 0);
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
new file mode 100644
index 0000000..e93df8c
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/gl/Texture.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.app.dualcam3d.gl;
+
+import android.graphics.Bitmap;
+import android.opengl.GLES20;
+import android.opengl.GLUtils;
+
+class Texture {
+    private final int[] mId = new int[1];
+    private boolean mInitialized = false;
+
+    private void init() {
+        if (!mInitialized) {
+            GLES20.glGenTextures(1, mId, 0);
+            Error.check();
+            mInitialized = true;
+        }
+    }
+
+    public void upload(Bitmap bitmap) {
+        init();
+
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+        Error.check();
+
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_NEAREST);
+        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+
+        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
+    }
+
+    public void bind() {
+        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mId[0]);
+        Error.check();
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
new file mode 100644
index 0000000..a3c6fda
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Controller.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d.threed;
+
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.app.dualcam3d.GLView;
+import com.android.gallery3d.app.dualcam3d.gl.Renderer;
+
+import org.codeaurora.gallery.R;
+
+public class Controller implements Gyro.Listener {
+    private static final String TAG = "Controller";
+    private static final float ANGLE_PER_PIXEL = (float) Math.toRadians(0.03f);
+
+    private final GLView mGLView;
+    private final LinearLayout mModeView;
+    private Auto mAuto;
+    private Gyro mGyro;
+
+    public Controller(GLView glView, LinearLayout modeView) {
+        mGLView = glView;
+        mModeView = modeView;
+        View.OnClickListener listener = v -> {
+            int id = v.getId();
+            switch (id) {
+                case R.id.mode_gyro:
+                    startGyro();
+                    break;
+                case R.id.mode_auto:
+                    startAuto();
+                    break;
+                case R.id.mode_touch:
+                    stop();
+                    break;
+                case R.id.three_dimensional:
+                    start();
+                    break;
+            }
+        };
+        for (int i = modeView.getChildCount() - 1; i >= 0; --i) {
+            ImageButton b = (ImageButton) modeView.getChildAt(i);
+            b.setOnClickListener(listener);
+        }
+    }
+
+    private boolean startGyro() {
+        stop();
+        if (mGyro == null) {
+            mGyro = new Gyro(mGLView.getContext());
+            if (mGyro.start()) {
+                mGyro.setListener(this);
+                return true;
+            } else {
+                mGyro = null;
+                mModeView.findViewById(R.id.mode_gyro).setEnabled(false);
+            }
+        }
+        return false;
+    }
+
+    private void startAuto() {
+        stop();
+        if (mAuto == null) {
+            mAuto = new Auto();
+            mAuto.start(mGLView);
+        }
+    }
+
+    public void start() {
+        if (!startGyro()) {
+            startAuto();
+        }
+    }
+
+    public void stop() {
+        if (mGyro != null) {
+            mGyro.stop();
+            mGyro = null;
+        }
+        if (mAuto != null) {
+            mAuto.stop();
+            mAuto = null;
+        }
+    }
+
+    @Override
+    public void onGyroChanged(float thetaX, float thetaY) {
+        mGLView.setOffsetWithRotation(thetaX, thetaY);
+    }
+
+    public void onMove(float deltaX, float deltaY) {
+        stop();
+        mGLView.setOffsetDelta(deltaX * ANGLE_PER_PIXEL, deltaY * ANGLE_PER_PIXEL);
+    }
+
+    private static class Auto {
+        private Thread mThread;
+        private boolean mStop;
+
+        public void start(final GLView glView) {
+            mStop = false;
+            mThread = new Thread(() -> {
+                float x = 0, y = 0, speed = 0.003f, angle = 0.87f;
+                double deltaX = angle * speed;
+                double deltaY = Math.sqrt(speed * speed - deltaX * deltaX);
+
+                while (!mStop) {
+                    x += deltaX;
+                    y += deltaY;
+                    glView.setOffset(x, y);
+
+                    if (x >= Renderer.THETA_MAX || x <= -Renderer.THETA_MAX) {
+                        deltaX = -deltaX;
+                    }
+                    if (y >= Renderer.THETA_MAX || y <= -Renderer.THETA_MAX) {
+                        deltaY = -deltaY;
+                    }
+                    try {
+                        Thread.sleep(15);
+                    } catch (InterruptedException e) {
+                        // ignore
+                    }
+                }
+            });
+            mThread.start();
+        }
+
+        public void stop() {
+            mStop = true;
+            if (mThread != null) {
+                try {
+                    mThread.join();
+                    mThread = null;
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
new file mode 100644
index 0000000..bb1d1c1
--- /dev/null
+++ b/src/com/android/gallery3d/app/dualcam3d/threed/Gyro.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.app.dualcam3d.threed;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+class Gyro implements SensorEventListener {
+    private final SensorManager mSensorManager;
+    private final Sensor mGyro;
+
+    private static final float ALPHA = 0.4f;
+    private static final float ALPHA_ORIGIN = 0.95f;
+
+    private long mPrevTimestamp;
+    private float mPrevThetaX;
+    private float mPrevThetaY;
+    private float mPrevOriginX;
+    private float mPrevOriginY;
+    private float mPrevOmegaX;
+    private float mPrevOmegaY;
+
+    private Listener mListener;
+
+    interface Listener {
+        void onGyroChanged(float thetaX, float thetaY);
+    }
+
+    Gyro(Context context) {
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        mGyro = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
+    }
+
+    public boolean start() {
+        return mGyro != null
+                && mSensorManager.registerListener(this, mGyro, SensorManager.SENSOR_DELAY_UI);
+    }
+
+    public void stop() {
+        mSensorManager.unregisterListener(this);
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
+            float omegaX = event.values[0];
+            float omegaY = event.values[1];
+            update(omegaX, omegaY, event.timestamp);
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    private void update(float omegaX, float omegaY, long timestamp) {
+        if (mPrevTimestamp == 0) {
+            mPrevTimestamp = timestamp;
+            return;
+        }
+        float deltaTimestamp = (float) (timestamp - mPrevTimestamp) / 1000_000_000;
+
+        float thetaX = mPrevThetaX + 0.5f * (mPrevOmegaX + omegaX) * deltaTimestamp;
+        float thetaY = mPrevThetaY + 0.5f * (mPrevOmegaY + omegaY) * deltaTimestamp;
+        float smoothThetaX = ALPHA * mPrevThetaX + ((1.0f - ALPHA) * thetaX);
+        float smoothThetaY = ALPHA * mPrevThetaY + ((1.0f - ALPHA) * thetaY);
+
+        mPrevOriginX = ALPHA_ORIGIN * mPrevOriginX + (1 - ALPHA_ORIGIN) * smoothThetaX;
+        mPrevOriginY = ALPHA_ORIGIN * mPrevOriginY + (1 - ALPHA_ORIGIN) * smoothThetaY;
+
+        mPrevTimestamp = timestamp;
+        mPrevOmegaX = omegaX;
+        mPrevOmegaY = omegaY;
+        mPrevThetaX = smoothThetaX;
+        mPrevThetaY = smoothThetaY;
+
+        if (mListener != null) {
+            mListener.onGyroChanged(smoothThetaX - mPrevOriginX, smoothThetaY - mPrevOriginY);
+        }
+    }
+
+    void setListener(Listener listener) {
+        mListener = listener;
+    }
+}
diff --git a/src/com/android/gallery3d/data/CameraShortcutImage.java b/src/com/android/gallery3d/data/CameraShortcutImage.java
index 865270b..0334c30 100644
--- a/src/com/android/gallery3d/data/CameraShortcutImage.java
+++ b/src/com/android/gallery3d/data/CameraShortcutImage.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.data;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 
 public class CameraShortcutImage extends ActionImage {
diff --git a/src/com/android/gallery3d/data/ClusterAlbum.java b/src/com/android/gallery3d/data/ClusterAlbum.java
old mode 100644
new mode 100755
index 8681952..df88c48
--- a/src/com/android/gallery3d/data/ClusterAlbum.java
+++ b/src/com/android/gallery3d/data/ClusterAlbum.java
@@ -17,6 +17,7 @@
 package com.android.gallery3d.data;
 
 import java.util.ArrayList;
+import com.android.gallery3d.util.GalleryUtils;
 
 public class ClusterAlbum extends MediaSet implements ContentListener {
     @SuppressWarnings("unused")
@@ -26,13 +27,22 @@
     private DataManager mDataManager;
     private MediaSet mClusterAlbumSet;
     private MediaItem mCover;
+    private final int INVALID_COUNT = -1;
+    private int mImageCount = INVALID_COUNT;
+    private int mVideoCount = INVALID_COUNT;
+    private int mKind = -1;
+
+
+    private TimeLineTitleMediaItem mTimelineTitleMediaItem;
 
     public ClusterAlbum(Path path, DataManager dataManager,
-            MediaSet clusterAlbumSet) {
+            MediaSet clusterAlbumSet, int kind) {
         super(path, nextVersionNumber());
         mDataManager = dataManager;
         mClusterAlbumSet = clusterAlbumSet;
         mClusterAlbumSet.addContentListener(this);
+        mKind = kind;
+        mTimelineTitleMediaItem = new TimeLineTitleMediaItem(path);
     }
 
     public void setCoverMediaItem(MediaItem cover) {
@@ -48,12 +58,16 @@
         mPaths = paths;
     }
 
-    ArrayList<Path> getMediaItems() {
+    public ArrayList<Path> getMediaItems() {
         return mPaths;
     }
 
     public void setName(String name) {
         mName = name;
+        mTimelineTitleMediaItem.setTitle(name);
+        /*if (mKind == ClusterSource.CLUSTER_ALBUMSET_TIME) {
+            mTimelineTitleMediaItem = new TimeLineTitleMediaItem(name);
+        }*/
     }
 
     @Override
@@ -63,18 +77,69 @@
 
     @Override
     public int getMediaItemCount() {
+        if (MediaSet.isShowAlbumsetTimeTitle()) {
+            return mPaths.size()+1;
+        }
         return mPaths.size();
     }
 
     @Override
+    public int getSelectableItemCount() {
+        return mPaths.size();
+    }
+
+    public void setImageItemCount(int count) {
+        mImageCount = count;
+        if (mTimelineTitleMediaItem != null && MediaSet.isShowAlbumsetTimeTitle()) {
+            mTimelineTitleMediaItem.setImageCount(count);
+        }
+    }
+
+    public void setVideoItemCount(int count) {
+        mVideoCount = count;
+        if (mTimelineTitleMediaItem != null && MediaSet.isShowAlbumsetTimeTitle()) {
+            mTimelineTitleMediaItem.setVideoCount(count);
+        }
+    }
+
+    private void updateItemCounts() {
+        setImageItemCount(mImageCount);
+        setVideoItemCount(mVideoCount);
+    }
+
+    @Override
     public ArrayList<MediaItem> getMediaItem(int start, int count) {
-        return getMediaItemFromPath(mPaths, start, count, mDataManager);
+        //return getMediaItemFromPath(mPaths, start, count, mDataManager);
+        updateItemCounts();
+        if (MediaSet.isShowAlbumsetTimeTitle()) {
+            if (mPaths.size() <= 0) return null;
+            if (start == 0) {
+                ArrayList<MediaItem> mediaItemList = new ArrayList<MediaItem>();
+                mediaItemList.addAll(getMediaItemFromPath(mPaths, start, count - 1, mDataManager));
+                mediaItemList.add(0, mTimelineTitleMediaItem);
+                return mediaItemList;
+            } else {
+                return getMediaItemFromPath(mPaths, start - 1, count, mDataManager);
+            }
+        } else {
+            return getMediaItemFromPath(mPaths, start, count, mDataManager);
+        }
+    }
+
+    @Override
+    public int getImageItemCount() {
+        return mImageCount;
+    }
+
+    @Override
+    public int getVideoItemCount() {
+        return mVideoCount;
     }
 
     public static ArrayList<MediaItem> getMediaItemFromPath(
             ArrayList<Path> paths, int start, int count,
             DataManager dataManager) {
-        if (start >= paths.size()) {
+        if (start >= paths.size() || start < 0) {
             return new ArrayList<MediaItem>();
         }
         int end = Math.min(start + count, paths.size());
@@ -89,7 +154,9 @@
         dataManager.mapMediaItems(subset, consumer, 0);
         ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start);
         for (int i = 0; i < buf.length; i++) {
-            result.add(buf[i]);
+            if(buf[i] != null) {
+                result.add(buf[i]);
+            }
         }
         return result;
     }
@@ -102,12 +169,33 @@
 
     @Override
     public int getTotalMediaItemCount() {
+        if (MediaSet.isShowAlbumsetTimeTitle()) {
+            return mPaths.size()+1;
+        }
         return mPaths.size();
     }
 
     @Override
+    public int getMediaType() {
+        // return correct type of Timeline Title.
+        if (MediaSet.isShowAlbumsetTimeTitle()) {
+            return MEDIA_TYPE_TIMELINE_TITLE;
+        }
+        return super.getMediaType();
+    }
+
+    @Override
+    public boolean isLoading() {
+        return mClusterAlbumSet.isLoading();
+    }
+
+    @Override
     public long reload() {
-        if (mClusterAlbumSet.reload() > mDataVersion) {
+        long version = mClusterAlbumSet.reload();
+        if (version == INVALID_DATA_VERSION) {
+            return INVALID_DATA_VERSION;
+        }
+        if (version > mDataVersion) {
             mDataVersion = nextVersionNumber();
         }
         return mDataVersion;
@@ -120,11 +208,16 @@
 
     @Override
     public int getSupportedOperations() {
+        // Timeline title item doesn't support anything, just its sub objects supported.
+        if (MediaSet.isShowAlbumsetTimeTitle()) {
+            return 0;
+        }
         return SUPPORT_SHARE | SUPPORT_DELETE | SUPPORT_INFO;
     }
 
     @Override
     public void delete() {
+        if ((getSupportedOperations() & MediaObject.SUPPORT_DELETE) == 0) return;
         ItemConsumer consumer = new ItemConsumer() {
             @Override
             public void consume(int index, MediaItem item) {
@@ -140,4 +233,9 @@
     public boolean isLeafAlbum() {
         return true;
     }
+
+    public TimeLineTitleMediaItem getTimelineTitle() {
+        return mTimelineTitleMediaItem;
+    }
+
 }
diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java
old mode 100644
new mode 100755
index cb212ba..0d7ce36
--- a/src/com/android/gallery3d/data/ClusterAlbumSet.java
+++ b/src/com/android/gallery3d/data/ClusterAlbumSet.java
@@ -22,7 +22,8 @@
 import com.android.gallery3d.app.GalleryApp;
 
 import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Arrays;
+import java.util.HashMap;
 
 public class ClusterAlbumSet extends MediaSet implements ContentListener {
     @SuppressWarnings("unused")
@@ -31,7 +32,13 @@
     private MediaSet mBaseSet;
     private int mKind;
     private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>();
-    private boolean mFirstReloadDone;
+    private boolean mIsLoading;
+
+    private int mTotalMediaItemCount;
+    /** mTotalSelectableMediaItemCount is the count of items
+     * exclude not selectable such as Title item in TimeLine. */
+    private int mTotalSelectableMediaItemCount;
+    private ArrayList<Integer> mAlbumItemCountList;
 
     public ClusterAlbumSet(Path path, GalleryApp application,
             MediaSet baseSet, int kind) {
@@ -58,15 +65,24 @@
     }
 
     @Override
+    public synchronized boolean isLoading() {
+        return mIsLoading;
+    }
+
+    @Override
     public long reload() {
-        if (mBaseSet.reload() > mDataVersion) {
-            if (mFirstReloadDone) {
-                updateClustersContents();
-            } else {
+        synchronized (this) {
+            long version = mBaseSet.reload();
+            mIsLoading = mBaseSet.isLoading();
+            if (version > mDataVersion && !mIsLoading) {
                 updateClusters();
-                mFirstReloadDone = true;
+                mIsLoading = false;
+                mDataVersion = nextVersionNumber();
             }
-            mDataVersion = nextVersionNumber();
+            if (mKind == ClusterSource.CLUSTER_ALBUMSET_TIME) {
+                calculateTotalItemsCount();
+                calculateTotalSelectableItemsCount();
+            }
         }
         return mDataVersion;
     }
@@ -77,6 +93,12 @@
     }
 
     private void updateClusters() {
+        //save last paths to find the empty albums
+        ArrayList<Path> oldPaths = new ArrayList<Path>();
+        for (ClusterAlbum album : mAlbums) {
+            oldPaths.add(album.getPath());
+        }
+
         mAlbums.clear();
         Clustering clustering;
         Context context = mApplication.getAndroidContext();
@@ -97,7 +119,6 @@
                 clustering = new SizeClustering(context);
                 break;
         }
-
         clustering.run(mBaseSet);
         int n = clustering.getNumberOfClusters();
         DataManager dataManager = mApplication.getDataManager();
@@ -117,22 +138,39 @@
             synchronized (DataManager.LOCK) {
                 album = (ClusterAlbum) dataManager.peekMediaObject(childPath);
                 if (album == null) {
-                    album = new ClusterAlbum(childPath, dataManager, this);
+                    album = new ClusterAlbum(childPath, dataManager, this, mKind);
                 }
             }
             album.setMediaItems(clustering.getCluster(i));
             album.setName(childName);
             album.setCoverMediaItem(clustering.getClusterCover(i));
+            album.setImageItemCount(clustering.getClusterImageCount(i));
+            album.setVideoItemCount(clustering.getClusterVideoCount(i));
             mAlbums.add(album);
+
+            int size = oldPaths.size();
+            for (int j = size - 1; j >= 0; j--) {
+                if (oldPaths.get(j) == childPath) {
+                    oldPaths.remove(j);
+                    break;
+                }
+            }
+        }
+        //set the empty path to the albums which don't exist from dataManger
+        for (Path path : oldPaths) {
+            ClusterAlbum album = (ClusterAlbum) dataManager.peekMediaObject(path);
+            if (album != null) {
+                album.setMediaItems(new ArrayList<Path>());
+            }
         }
     }
 
-    private void updateClustersContents() {
-        final HashSet<Path> existing = new HashSet<Path>();
+    protected void updateClustersContents() {
+        final HashMap<Path, Integer> existing = new HashMap<Path, Integer>();
         mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
             @Override
             public void consume(int index, MediaItem item) {
-                existing.add(item.getPath());
+                existing.put(item.getPath(), item.getMediaType());
             }
         });
 
@@ -144,16 +182,108 @@
             ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems();
             ArrayList<Path> newPaths = new ArrayList<Path>();
             int m = oldPaths.size();
+            int imageCount = 0;
+            int videoCount = 0;
+            int mediaType = MEDIA_TYPE_UNKNOWN;
+            ClusterAlbum album = mAlbums.get(i);
             for (int j = 0; j < m; j++) {
                 Path p = oldPaths.get(j);
-                if (existing.contains(p)) {
+                if (existing.containsKey(p)) {
                     newPaths.add(p);
+                    mediaType = existing.get(p);
+                    existing.remove(p);
+                    if(mediaType == MediaObject.MEDIA_TYPE_IMAGE) {
+                        imageCount++;
+                    } else if(mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
+                        videoCount++;
+                    }
                 }
             }
-            mAlbums.get(i).setMediaItems(newPaths);
+            album.setImageItemCount(imageCount);
+            album.setVideoItemCount(videoCount);
+            album.setMediaItems(newPaths);
             if (newPaths.isEmpty()) {
                 mAlbums.remove(i);
             }
         }
+
+        updateClusters();
     }
+
+    private void calculateTotalSelectableItemsCount() {
+        mTotalSelectableMediaItemCount = 0;
+        if (mAlbums != null && mAlbums.size() > 0) {
+            for (ClusterAlbum album : mAlbums) {
+                int count = album.getSelectableItemCount();
+                mTotalSelectableMediaItemCount += count;
+            }
+        }
+    }
+
+    @Override
+    public int getSelectableItemCount() {
+        return mTotalSelectableMediaItemCount;
+    }
+
+  private void calculateTotalItemsCount() {
+      mTotalMediaItemCount = 0;
+      if( mAlbums != null && mAlbums.size() > 0) {
+          mAlbumItemCountList = new ArrayList<Integer>();
+          for(ClusterAlbum album: mAlbums) {
+              int count = album.getMediaItemCount();
+              mTotalMediaItemCount = mTotalMediaItemCount + count;
+              mAlbumItemCountList.add(mTotalMediaItemCount);
+          }
+      }
+  }
+
+  @Override
+  public int getMediaItemCount() {
+      return mTotalMediaItemCount;
+  }
+
+  @Override
+  public ArrayList<MediaItem> getMediaItem(int start, int count) {
+      if ((start + count) > mTotalMediaItemCount ) {
+          count  = mTotalMediaItemCount - start;
+      }
+      if (count <= 0) return null;
+      ArrayList<MediaItem> mediaItems = new ArrayList<MediaItem>();
+      int startAlbum = findTimelineAlbumIndex(start);
+      int endAlbum = findTimelineAlbumIndex(start + count - 1);
+      int s;
+      int lCount;
+      if (mAlbums.size() > 0 && mAlbumItemCountList.size() > 0) {
+          s = mAlbums.get(startAlbum).getTotalMediaItemCount() -
+                  (mAlbumItemCountList.get(startAlbum) - start);
+          for (int i = startAlbum; i <= endAlbum && i < mAlbums.size(); ++i) {
+              int albumCount = mAlbums.get(i).getTotalMediaItemCount();
+              lCount = Math.min(albumCount - s, count);
+              ArrayList<MediaItem> items = mAlbums.get(i).getMediaItem(s, lCount);
+              if (items != null)
+                  mediaItems.addAll(items);
+              count -= lCount;
+              s = 0;
+          }
+      }
+      return mediaItems;
+  }
+
+  public int findTimelineAlbumIndex(int itemIndex) {
+      int index = Arrays.binarySearch(mAlbumItemCountList.toArray(new Integer[0]), itemIndex);
+      if (index <  mTotalMediaItemCount && index >=  0)
+          return index + 1;
+      if (index < 0) {
+          index = (index * (-1)) - 1;
+      }
+      return index;
+  }
+
+  public ClusterAlbum getAlbumFromindex(int index) {
+      int aIndex = findTimelineAlbumIndex(index);
+      if (aIndex < mAlbums.size() && aIndex >= 0) {
+          return mAlbums.get(aIndex);
+      }
+      return null;
+  }
 }
diff --git a/src/com/android/gallery3d/data/ClusterSource.java b/src/com/android/gallery3d/data/ClusterSource.java
index a1f22e5..f4ef110 100644
--- a/src/com/android/gallery3d/data/ClusterSource.java
+++ b/src/com/android/gallery3d/data/ClusterSource.java
@@ -77,7 +77,7 @@
                 MediaSet parent = dataManager.getMediaSet(path.getParent());
                 // The actual content in the ClusterAlbum will be filled later
                 // when the reload() method in the parent is run.
-                return new ClusterAlbum(path, dataManager, parent);
+                return new ClusterAlbum(path, dataManager, parent, matchType);
             }
             default:
                 throw new RuntimeException("bad path: " + path);
diff --git a/src/com/android/gallery3d/data/Clustering.java b/src/com/android/gallery3d/data/Clustering.java
index 4072bf5..204bd1a 100644
--- a/src/com/android/gallery3d/data/Clustering.java
+++ b/src/com/android/gallery3d/data/Clustering.java
@@ -26,4 +26,12 @@
     public MediaItem getClusterCover(int index) {
         return null;
     }
+
+    public int getClusterImageCount(int index) {
+        return 0;
+    }
+
+    public int getClusterVideoCount(int index) {
+        return 0;
+    }
 }
diff --git a/src/com/android/gallery3d/data/ComboAlbumSet.java b/src/com/android/gallery3d/data/ComboAlbumSet.java
index 3f36745..1c50885 100644
--- a/src/com/android/gallery3d/data/ComboAlbumSet.java
+++ b/src/com/android/gallery3d/data/ComboAlbumSet.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.data;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.util.Future;
 
diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java
index 38865e9..5c7664c 100644
--- a/src/com/android/gallery3d/data/DataManager.java
+++ b/src/com/android/gallery3d/data/DataManager.java
@@ -242,7 +242,12 @@
 
     // The following methods forward the request to the proper object.
     public int getSupportedOperations(Path path) {
-        return getMediaObject(path).getSupportedOperations();
+        int support = 0;
+        MediaObject mediaObject = getMediaObject(path);
+        if (mediaObject != null) {
+            support = mediaObject.getSupportedOperations();
+        }
+        return support;
     }
 
     public void getPanoramaSupport(Path path, PanoramaSupportCallback callback) {
@@ -250,7 +255,10 @@
     }
 
     public void delete(Path path) {
-        getMediaObject(path).delete();
+        MediaObject mediaObject = getMediaObject(path);
+        if (mediaObject != null) {
+            mediaObject.delete();
+        }
     }
 
     public void rotate(Path path, int degrees) {
diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java
index 2853baf..62f83c9 100644
--- a/src/com/android/gallery3d/data/DecodeUtils.java
+++ b/src/com/android/gallery3d/data/DecodeUtils.java
@@ -139,6 +139,8 @@
         } else {
             // For screen nail, we only want to keep the longer side >= targetSize.
             float scale = (float) targetSize / Math.max(w, h);
+            if (scale < 0.2) scale *= 2;
+            Log.d(TAG, "decodeThumbnail scale=" + scale);
             options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
         }
 
diff --git a/src/com/android/gallery3d/data/EmptyAlbumImage.java b/src/com/android/gallery3d/data/EmptyAlbumImage.java
index 6f8c37c..c055d57 100644
--- a/src/com/android/gallery3d/data/EmptyAlbumImage.java
+++ b/src/com/android/gallery3d/data/EmptyAlbumImage.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.data;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 
 public class EmptyAlbumImage extends ActionImage {
diff --git a/src/com/android/gallery3d/data/FaceClustering.java b/src/com/android/gallery3d/data/FaceClustering.java
old mode 100644
new mode 100755
index 819915e..0bdef08
--- a/src/com/android/gallery3d/data/FaceClustering.java
+++ b/src/com/android/gallery3d/data/FaceClustering.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.graphics.Rect;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.picasasource.PicasaSource;
 
 import java.util.ArrayList;
@@ -83,7 +83,7 @@
     }
 
     public FaceClustering(Context context) {
-        mUntaggedString = context.getResources().getString(R.string.untagged);
+        mUntaggedString = context.getResources().getString(R.string.no_faces);
         mContext = context;
     }
 
diff --git a/src/com/android/gallery3d/data/FilterDeleteSet.java b/src/com/android/gallery3d/data/FilterDeleteSet.java
old mode 100644
new mode 100755
index c76412f..d0b5b0a
--- a/src/com/android/gallery3d/data/FilterDeleteSet.java
+++ b/src/com/android/gallery3d/data/FilterDeleteSet.java
@@ -35,6 +35,8 @@
     private static final int REQUEST_REMOVE = 2;
     private static final int REQUEST_CLEAR = 3;
 
+    private boolean mIsLoading;
+
     private static class Request {
         int type;  // one of the REQUEST_* constants
         Path path;
@@ -136,17 +138,28 @@
         for (int m = j - 1; m >= i; m--) {
             Deletion d = mCurrent.get(m);
             int k = d.index - (start + i);
-            base.remove(k);
+            if (k >= 0 && k < base.size()) {
+                base.remove(k);
+            }
         }
         return base;
     }
 
+    @Override
+    public boolean isLoading() {
+        return mIsLoading;
+    }
+
     // We apply the pending requests in the mRequests to construct mCurrent in reload().
     @Override
     public long reload() {
+        mIsLoading = true;
         boolean newData = mBaseSet.reload() > mDataVersion;
         synchronized (mRequests) {
             if (!newData && mRequests.isEmpty()) {
+                if (!mBaseSet.isLoading()) {
+                    mIsLoading = false;
+                }
                 return mDataVersion;
             }
             for (int i = 0; i < mRequests.size(); i++) {
@@ -220,9 +233,17 @@
         }
 
         mDataVersion = nextVersionNumber();
+        if (!mBaseSet.isLoading()) {
+            mIsLoading = false;
+        }
         return mDataVersion;
     }
 
+    @Override
+    public int getCurrectSize() {
+        return mCurrent.size();
+    }
+
     private void sendRequest(int type, Path path, int indexHint) {
         Request r = new Request(type, path, indexHint);
         synchronized (mRequests) {
@@ -253,4 +274,5 @@
     public int getNumberOfDeletions() {
         return mCurrent.size();
     }
+
 }
diff --git a/src/com/android/gallery3d/data/FilterTypeSet.java b/src/com/android/gallery3d/data/FilterTypeSet.java
old mode 100644
new mode 100755
index 477ef73..50a7c69
--- a/src/com/android/gallery3d/data/FilterTypeSet.java
+++ b/src/com/android/gallery3d/data/FilterTypeSet.java
@@ -64,6 +64,10 @@
                 mPaths, start, count, mDataManager);
     }
 
+    public ArrayList<Path> getPaths() {
+        return mPaths;
+    }
+
     @Override
     public long reload() {
         if (mBaseSet.reload() > mDataVersion) {
@@ -88,12 +92,18 @@
             String filteredPath = basePath + "/{" + set.getPath().toString() + "}";
             MediaSet filteredSet = mDataManager.getMediaSet(filteredPath);
             filteredSet.reload();
+            if (filteredSet instanceof FilterTypeSet && ((FilterTypeSet)filteredSet).getPaths() != null) {
+                mPaths.addAll(((FilterTypeSet)filteredSet).getPaths());
+            }
             if (filteredSet.getMediaItemCount() > 0
                     || filteredSet.getSubMediaSetCount() > 0) {
                 mAlbums.add(filteredSet);
             }
         }
 
+        if (mPaths.size() > 0) {
+            return;
+        }
         // Items
         mPaths.clear();
         final int total = mBaseSet.getMediaItemCount();
@@ -102,7 +112,8 @@
         mBaseSet.enumerateMediaItems(new MediaSet.ItemConsumer() {
             @Override
             public void consume(int index, MediaItem item) {
-                if (item.getMediaType() == mMediaType) {
+                if (item.getMediaType() == mMediaType
+                        || item.getMediaType() == MediaObject.MEDIA_TYPE_DRM_IMAGE) {
                     if (index < 0 || index >= total) return;
                     Path path = item.getPath();
                     buf[index] = path;
diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java
index 6cbc5c5..90fb28c 100644
--- a/src/com/android/gallery3d/data/ImageCacheRequest.java
+++ b/src/com/android/gallery3d/data/ImageCacheRequest.java
@@ -16,8 +16,10 @@
 
 package com.android.gallery3d.data;
 
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.text.TextUtils;
 
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.common.BitmapUtils;
@@ -32,6 +34,8 @@
     private Path mPath;
     private int mType;
     private int mTargetSize;
+    private String mFilePath;
+    private String mMimeType;
     private long mTimeModified;
 
     public ImageCacheRequest(GalleryApp application,
@@ -43,6 +47,14 @@
         mTimeModified = timeModified;
     }
 
+    public ImageCacheRequest(GalleryApp application,
+            Path path, long timeModified, int type, int targetSize, String filepath, String mimeType) {
+        this(application, path, timeModified, type,
+                targetSize);
+        mFilePath = filepath;
+        mMimeType = mimeType;
+    }
+
     private String debugTag() {
         return mPath + "," + mTimeModified + "," +
                 ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" :
@@ -51,6 +63,14 @@
 
     @Override
     public Bitmap run(JobContext jc) {
+//        if (!TextUtils.isEmpty(mFilePath) && !TextUtils.isEmpty(mMimeType)
+//                && !mMimeType.startsWith("video/")) {
+//            if (DrmHelper.isDrmFile(mFilePath)
+//                    && mType != MediaItem.TYPE_MICROTHUMBNAIL) {
+//                return onDecodeOriginal(jc, mType);
+//            }
+//        }
+
         ImageCacheService cacheService = mApplication.getImageCacheService();
 
         BytesBuffer buffer = MediaItem.getBytesBufferPool().get();
@@ -76,6 +96,7 @@
         } finally {
             MediaItem.getBytesBufferPool().recycle(buffer);
         }
+
         Bitmap bitmap = onDecodeOriginal(jc, mType);
         if (jc.isCancelled()) return null;
 
diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java
index 1c7cb8c..861d4b7 100644
--- a/src/com/android/gallery3d/data/ImageCacheService.java
+++ b/src/com/android/gallery3d/data/ImageCacheService.java
@@ -56,12 +56,17 @@
      * @return true if the image data is found; false if not found.
      */
     public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) {
+        if (mCache == null) return false;
+
         byte[] key = makeKey(path, timeModified, type);
         long cacheKey = Utils.crc64Long(key);
         try {
             LookupRequest request = new LookupRequest();
             request.key = cacheKey;
             request.buffer = buffer.data;
+            if (mCache == null) {
+                return false;
+            }
             synchronized (mCache) {
                 if (!mCache.lookup(request)) return false;
             }
@@ -78,11 +83,16 @@
     }
 
     public void putImageData(Path path, long timeModified, int type, byte[] value) {
+        if (mCache == null) return;
+
         byte[] key = makeKey(path, timeModified, type);
         long cacheKey = Utils.crc64Long(key);
         ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length);
         buffer.put(key);
         buffer.put(value);
+        if (mCache == null) {
+            return;
+        }
         synchronized (mCache) {
             try {
                 mCache.insert(cacheKey, buffer.array());
@@ -93,8 +103,13 @@
     }
 
     public void clearImageData(Path path, long timeModified, int type) {
+        if (mCache == null) return;
+
         byte[] key = makeKey(path, timeModified, type);
         long cacheKey = Utils.crc64Long(key);
+        if (mCache == null) {
+            return;
+        }
         synchronized (mCache) {
             try {
                 mCache.clearEntry(cacheKey);
diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java
index 7b7015a..2592a89 100644
--- a/src/com/android/gallery3d/data/LocalAlbum.java
+++ b/src/com/android/gallery3d/data/LocalAlbum.java
@@ -27,7 +27,7 @@
 import android.provider.MediaStore.Video;
 import android.provider.MediaStore.Video.VideoColumns;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.util.BucketNames;
@@ -75,7 +75,11 @@
             mProjection = LocalImage.PROJECTION;
             mItemPath = LocalImage.ITEM_PATH;
         } else {
+            if (mBucketId == -1) {
+                mWhereClause = null;
+            } else {
             mWhereClause = VideoColumns.BUCKET_ID + " = ?";
+            }
             mOrderClause = VideoColumns.DATE_TAKEN + " DESC, "
                     + VideoColumns._ID + " DESC";
             mBaseUri = Video.Media.EXTERNAL_CONTENT_URI;
@@ -88,9 +92,10 @@
 
     public LocalAlbum(Path path, GalleryApp application, int bucketId,
             boolean isImage) {
-        this(path, application, bucketId, isImage,
-                BucketHelper.getBucketName(
-                application.getContentResolver(), bucketId));
+        this(path, application, bucketId, isImage, bucketId == -1 ? application
+                .getAndroidContext().getString(R.string.videos_title)
+                : BucketHelper.getBucketName(application.getContentResolver(),
+                        bucketId));
     }
 
     @Override
@@ -118,10 +123,16 @@
                 .appendQueryParameter("limit", start + "," + count).build();
         ArrayList<MediaItem> list = new ArrayList<MediaItem>();
         GalleryUtils.assertNotInRenderThread();
-        Cursor cursor = mResolver.query(
+        Cursor cursor;
+        if (mBucketId == -1) {
+            cursor = mResolver.query(uri, mProjection, mWhereClause, null,
+                    mOrderClause);
+        } else {
+            cursor = mResolver.query(
                 uri, mProjection, mWhereClause,
                 new String[]{String.valueOf(mBucketId)},
                 mOrderClause);
+        }
         if (cursor == null) {
             Log.w(TAG, "query fail: " + uri);
             return list;
@@ -229,9 +240,15 @@
     @Override
     public int getMediaItemCount() {
         if (mCachedCount == INVALID_COUNT) {
-            Cursor cursor = mResolver.query(
+            Cursor cursor;
+            if (mBucketId == -1) {
+                cursor = mResolver.query(mBaseUri, COUNT_PROJECTION,
+                        mWhereClause, null, mOrderClause);
+            } else {
+                cursor = mResolver.query(
                     mBaseUri, COUNT_PROJECTION, mWhereClause,
                     new String[]{String.valueOf(mBucketId)}, null);
+            }
             if (cursor == null) {
                 Log.w(TAG, "query fail");
                 return 0;
diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java
index b2b4b8c..81e7d80 100644
--- a/src/com/android/gallery3d/data/LocalAlbumSet.java
+++ b/src/com/android/gallery3d/data/LocalAlbumSet.java
@@ -21,7 +21,7 @@
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Video;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.data.BucketHelper.BucketEntry;
 import com.android.gallery3d.util.Future;
diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java
old mode 100644
new mode 100755
index 2b01c1e..1b5c88b
--- a/src/com/android/gallery3d/data/LocalImage.java
+++ b/src/com/android/gallery3d/data/LocalImage.java
@@ -20,6 +20,7 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
@@ -132,7 +133,6 @@
 
     private void loadFromCursor(Cursor cursor) {
         id = cursor.getInt(INDEX_ID);
-        caption = cursor.getString(INDEX_CAPTION);
         mimeType = cursor.getString(INDEX_MIME_TYPE);
         latitude = cursor.getDouble(INDEX_LATITUDE);
         longitude = cursor.getDouble(INDEX_LONGITUDE);
@@ -140,6 +140,7 @@
         dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
         dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
         filePath = cursor.getString(INDEX_DATA);
+        caption = getPathTile(filePath);
         rotation = cursor.getInt(INDEX_ORIENTATION);
         bucketId = cursor.getInt(INDEX_BUCKET_ID);
         fileSize = cursor.getLong(INDEX_SIZE);
@@ -151,7 +152,6 @@
     protected boolean updateFromCursor(Cursor cursor) {
         UpdateHelper uh = new UpdateHelper();
         id = uh.update(id, cursor.getInt(INDEX_ID));
-        caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
         mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
         latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
         longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
@@ -162,6 +162,7 @@
         dateModifiedInSec = uh.update(
                 dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
         filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
+        caption = uh.update(caption, getPathTile(filePath));
         rotation = uh.update(rotation, cursor.getInt(INDEX_ORIENTATION));
         bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
         fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE));
@@ -173,7 +174,7 @@
     @Override
     public Job<Bitmap> requestImage(int type) {
         return new LocalImageRequest(mApplication, mPath, dateModifiedInSec,
-                type, filePath);
+                type, filePath, mimeType);
     }
 
     public static class LocalImageRequest extends ImageCacheRequest {
@@ -186,10 +187,23 @@
             mLocalFilePath = localFilePath;
         }
 
+        LocalImageRequest(GalleryApp application, Path path, long timeModified,
+                int type, String localFilePath, String mimeType) {
+            super(application, path, timeModified, type,
+                    MediaItem.getTargetSize(type),localFilePath, mimeType);
+            mLocalFilePath = localFilePath;
+        }
+
         @Override
         public Bitmap onDecodeOriginal(JobContext jc, final int type) {
             BitmapFactory.Options options = new BitmapFactory.Options();
             options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+
+//            if (DrmHelper.isDrmFile(mLocalFilePath)) {
+//                return DecodeUtils.ensureGLCompatibleBitmap(DrmHelper
+//                        .getBitmap(mLocalFilePath, options));
+//            }
+
             int targetSize = MediaItem.getTargetSize(type);
 
             // try to decode from JPEG EXIF
@@ -230,25 +244,43 @@
 
         @Override
         public BitmapRegionDecoder run(JobContext jc) {
+//            if (DrmHelper.isDrmFile(mLocalFilePath)) {
+//                return DrmHelper.createBitmapRegionDecoder(mLocalFilePath,
+//                        false);
+//            }
+
             return DecodeUtils.createBitmapRegionDecoder(jc, mLocalFilePath, false);
         }
     }
 
     @Override
     public int getSupportedOperations() {
-        int operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP
+        int operation = SUPPORT_DELETE | SUPPORT_INFO;
+
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            if (DrmHelper.isDrmFLBlocking(mApplication.getAndroidContext(),
+//                    getFilePath())) {
+//                operation |= SUPPORT_SETAS;
+//            }
+//            operation |= SUPPORT_DRM_INFO | SUPPORT_FULL_IMAGE;
+//            if (DrmHelper.isShareableDrmFile(getFilePath())) {
+//                operation |= SUPPORT_SHARE;
+//            }
+//        } else {
+            operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP
                 | SUPPORT_SETAS | SUPPORT_PRINT | SUPPORT_INFO;
-        if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) {
-            operation |= SUPPORT_FULL_IMAGE | SUPPORT_EDIT;
-        }
+            if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) {
+                operation |= SUPPORT_FULL_IMAGE | SUPPORT_EDIT;
+            }
 
-        if (BitmapUtils.isRotationSupported(mimeType)) {
-            operation |= SUPPORT_ROTATE;
-        }
+            if (BitmapUtils.isRotationSupported(mimeType)) {
+                operation |= SUPPORT_ROTATE;
+            }
 
-        if (GalleryUtils.isValidLocation(latitude, longitude)) {
-            operation |= SUPPORT_SHOW_ON_MAP;
-        }
+            if (GalleryUtils.isValidLocation(latitude, longitude)) {
+                operation |= SUPPORT_SHOW_ON_MAP;
+            }
+//        }
         return operation;
     }
 
@@ -313,6 +345,10 @@
 
     @Override
     public int getMediaType() {
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            return MEDIA_TYPE_DRM_IMAGE;
+//        }
+
         return MEDIA_TYPE_IMAGE;
     }
 
@@ -320,7 +356,8 @@
     public MediaDetails getDetails() {
         MediaDetails details = super.getDetails();
         details.addDetail(MediaDetails.INDEX_ORIENTATION, Integer.valueOf(rotation));
-        if (MIME_TYPE_JPEG.equals(mimeType)) {
+        if (MIME_TYPE_JPEG.equals(mimeType) || MIME_TYPE_HEIF.equals(mimeType) ||
+                MIME_TYPE_HEIC.equals(mimeType)) {
             // ExifInterface returns incorrect values for photos in other format.
             // For example, the width and height of an webp images is always '0'.
             MediaDetails.extractExifInfo(details, filePath);
diff --git a/src/com/android/gallery3d/data/LocalMediaItem.java b/src/com/android/gallery3d/data/LocalMediaItem.java
old mode 100644
new mode 100755
index 7e003cd..03156d3
--- a/src/com/android/gallery3d/data/LocalMediaItem.java
+++ b/src/com/android/gallery3d/data/LocalMediaItem.java
@@ -61,6 +61,23 @@
         return caption;
     }
 
+    public String getPathTile(String path) {
+        // extract file name after last slash
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash >= 0) {
+            lastSlash++;
+            if (lastSlash < path.length()) {
+                path = path.substring(lastSlash);
+            }
+        }
+        // truncate the file extension (if any)
+        int lastDot = path.lastIndexOf('.');
+        if (lastDot > 0) {
+            path = path.substring(0, lastDot);
+        }
+        return path;
+    }
+
     @Override
     public void getLatLong(double[] latLong) {
         latLong[0] = latitude;
diff --git a/src/com/android/gallery3d/data/LocalMergeAlbum.java b/src/com/android/gallery3d/data/LocalMergeAlbum.java
index f0b5e57..db981c3 100644
--- a/src/com/android/gallery3d/data/LocalMergeAlbum.java
+++ b/src/com/android/gallery3d/data/LocalMergeAlbum.java
@@ -36,7 +36,7 @@
 public class LocalMergeAlbum extends MediaSet implements ContentListener {
     @SuppressWarnings("unused")
     private static final String TAG = "LocalMergeAlbum";
-    private static final int PAGE_SIZE = 64;
+    private static final int PAGE_SIZE = 1024;
 
     private final Comparator<MediaItem> mComparator;
     private final MediaSet[] mSources;
diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java
old mode 100644
new mode 100755
index 4b8774c..787e7f0
--- a/src/com/android/gallery3d/data/LocalVideo.java
+++ b/src/com/android/gallery3d/data/LocalVideo.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.database.Cursor;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.graphics.BitmapRegionDecoder;
 import android.net.Uri;
@@ -100,7 +101,6 @@
 
     private void loadFromCursor(Cursor cursor) {
         id = cursor.getInt(INDEX_ID);
-        caption = cursor.getString(INDEX_CAPTION);
         mimeType = cursor.getString(INDEX_MIME_TYPE);
         latitude = cursor.getDouble(INDEX_LATITUDE);
         longitude = cursor.getDouble(INDEX_LONGITUDE);
@@ -108,6 +108,7 @@
         dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED);
         dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED);
         filePath = cursor.getString(INDEX_DATA);
+        caption = getPathTile(filePath);
         durationInSec = cursor.getInt(INDEX_DURATION) / 1000;
         bucketId = cursor.getInt(INDEX_BUCKET_ID);
         fileSize = cursor.getLong(INDEX_SIZE);
@@ -132,7 +133,6 @@
     protected boolean updateFromCursor(Cursor cursor) {
         UpdateHelper uh = new UpdateHelper();
         id = uh.update(id, cursor.getInt(INDEX_ID));
-        caption = uh.update(caption, cursor.getString(INDEX_CAPTION));
         mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE));
         latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE));
         longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE));
@@ -143,6 +143,7 @@
         dateModifiedInSec = uh.update(
                 dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED));
         filePath = uh.update(filePath, cursor.getString(INDEX_DATA));
+        caption = uh.update(caption, getPathTile(filePath));
         durationInSec = uh.update(
                 durationInSec, cursor.getInt(INDEX_DURATION) / 1000);
         bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID));
@@ -153,7 +154,7 @@
     @Override
     public Job<Bitmap> requestImage(int type) {
         return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec,
-                type, filePath);
+                type, filePath, mimeType);
     }
 
     public static class LocalVideoRequest extends ImageCacheRequest {
@@ -166,6 +167,13 @@
             mLocalFilePath = localFilePath;
         }
 
+        LocalVideoRequest(GalleryApp application, Path path, long timeModified,
+                int type, String localFilePath, String mimeType) {
+            super(application, path, timeModified, type,
+                    MediaItem.getTargetSize(type), localFilePath, mimeType);
+            mLocalFilePath = localFilePath;
+        }
+
         @Override
         public Bitmap onDecodeOriginal(JobContext jc, int type) {
             Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath);
@@ -182,7 +190,17 @@
 
     @Override
     public int getSupportedOperations() {
-        return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE;
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            int operation = SUPPORT_DELETE | SUPPORT_PLAY | SUPPORT_INFO
+//                    | SUPPORT_DRM_INFO;
+//            if (DrmHelper.isShareableDrmFile(getFilePath())) {
+//                operation |= SUPPORT_SHARE;
+//            }
+//            return operation;
+//        }
+
+        return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO
+                | SUPPORT_TRIM | SUPPORT_MUTE;
     }
 
     @Override
@@ -211,6 +229,10 @@
 
     @Override
     public int getMediaType() {
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            return MEDIA_TYPE_DRM_VIDEO;
+//        }
+
         return MEDIA_TYPE_VIDEO;
     }
 
diff --git a/src/com/android/gallery3d/data/LocationClustering.java b/src/com/android/gallery3d/data/LocationClustering.java
index 90ac41c..8cc2ad1 100644
--- a/src/com/android/gallery3d/data/LocationClustering.java
+++ b/src/com/android/gallery3d/data/LocationClustering.java
@@ -21,7 +21,7 @@
 import android.os.Looper;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.util.GalleryUtils;
 import com.android.gallery3d.util.ReverseGeocoder;
 
diff --git a/src/com/android/gallery3d/data/MediaDetails.java b/src/com/android/gallery3d/data/MediaDetails.java
old mode 100644
new mode 100755
index cac524b..7f32473
--- a/src/com/android/gallery3d/data/MediaDetails.java
+++ b/src/com/android/gallery3d/data/MediaDetails.java
@@ -16,16 +16,12 @@
 
 package com.android.gallery3d.data;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.Utils;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.exif.ExifInterface;
 import com.android.gallery3d.exif.ExifTag;
-import com.android.gallery3d.exif.Rational;
 
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map.Entry;
@@ -50,15 +46,16 @@
     public static final int INDEX_SIZE = 10;
 
     // for EXIF
-    public static final int INDEX_MAKE = 100;
-    public static final int INDEX_MODEL = 101;
-    public static final int INDEX_FLASH = 102;
-    public static final int INDEX_FOCAL_LENGTH = 103;
-    public static final int INDEX_WHITE_BALANCE = 104;
-    public static final int INDEX_APERTURE = 105;
-    public static final int INDEX_SHUTTER_SPEED = 106;
-    public static final int INDEX_EXPOSURE_TIME = 107;
-    public static final int INDEX_ISO = 108;
+    public static final int INDEX_DATETIME_ORIGINAL = 100;
+    public static final int INDEX_MAKE = 101;
+    public static final int INDEX_MODEL = 102;
+    public static final int INDEX_FLASH = 103;
+    public static final int INDEX_FOCAL_LENGTH = 104;
+    public static final int INDEX_WHITE_BALANCE = 105;
+    public static final int INDEX_APERTURE = 106;
+    public static final int INDEX_SHUTTER_SPEED = 107;
+    public static final int INDEX_EXPOSURE_TIME = 108;
+    public static final int INDEX_ISO = 109;
 
     // Put this last because it may be long.
     public static final int INDEX_PATH = 200;
@@ -148,6 +145,14 @@
                 MediaDetails.INDEX_WIDTH);
         setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_LENGTH),
                 MediaDetails.INDEX_HEIGHT);
+        ExifTag recordTag = exif.getTag(ExifInterface.TAG_DATE_TIME_ORIGINAL);
+        if (recordTag == null) {
+            recordTag = exif.getTag(ExifInterface.TAG_DATE_TIME_DIGITIZED);
+        }
+        if (recordTag == null) {
+            recordTag = exif.getTag(ExifInterface.TAG_DATE_TIME);
+        }
+        setExifData(details, recordTag, MediaDetails.INDEX_DATETIME_ORIGINAL);
         setExifData(details, exif.getTag(ExifInterface.TAG_MAKE),
                 MediaDetails.INDEX_MAKE);
         setExifData(details, exif.getTag(ExifInterface.TAG_MODEL),
@@ -166,5 +171,12 @@
                     focalTag.getValueAsRational(0).toDouble());
             details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm);
         }
+        ExifTag latitudeTag = exif.getTag(ExifInterface.TAG_GPS_LATITUDE);
+        ExifTag longitudeTag = exif.getTag(ExifInterface.TAG_GPS_LONGITUDE);
+        if (latitudeTag != null && longitudeTag != null) {
+            double latitude = latitudeTag.getValueAsRational(0).toDouble();
+            double longitude = longitudeTag.getValueAsRational(0).toDouble();
+            details.addDetail(MediaDetails.INDEX_LOCATION, new double[] {latitude, longitude});
+        }
     }
 }
diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java
old mode 100644
new mode 100755
index 59ea865..da58136
--- a/src/com/android/gallery3d/data/MediaItem.java
+++ b/src/com/android/gallery3d/data/MediaItem.java
@@ -37,6 +37,9 @@
     public static final int IMAGE_ERROR = -1;
 
     public static final String MIME_TYPE_JPEG = "image/jpeg";
+    public static final String MIME_TYPE_HEIF = "image/heif";
+    public static final String MIME_TYPE_HEIC = "image/heic";
+    public static final String MIME_TYPE_GIF = "image/gif";
 
     private static final int BYTESBUFFE_POOL_SIZE = 4;
     private static final int BYTESBUFFER_SIZE = 200 * 1024;
@@ -56,6 +59,9 @@
     public MediaItem(Path path, long version) {
         super(path, version);
     }
+    public MediaItem(Path path) {
+        super(path);
+    }
 
     public long getDateInMs() {
         return 0;
@@ -126,7 +132,7 @@
     }
 
     public static void setThumbnailSizes(int size, int microSize) {
-        sThumbnailTargetSize = size;
+        sThumbnailTargetSize = Math.max(size, sThumbnailTargetSize);
         if (sMicrothumbnailTargetSize != microSize) {
             sMicrothumbnailTargetSize = microSize;
         }
diff --git a/src/com/android/gallery3d/data/MediaObject.java b/src/com/android/gallery3d/data/MediaObject.java
index 530ee30..61f6d7c 100644
--- a/src/com/android/gallery3d/data/MediaObject.java
+++ b/src/com/android/gallery3d/data/MediaObject.java
@@ -42,13 +42,18 @@
     public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 15;
     public static final int SUPPORT_MUTE = 1 << 16;
     public static final int SUPPORT_PRINT = 1 << 17;
+    public static final int SUPPORT_DRM_INFO = 1 << 18;
     public static final int SUPPORT_ALL = 0xffffffff;
 
     // These are the bits returned from getMediaType():
     public static final int MEDIA_TYPE_UNKNOWN = 1;
     public static final int MEDIA_TYPE_IMAGE = 2;
     public static final int MEDIA_TYPE_VIDEO = 4;
+    public static final int MEDIA_TYPE_DRM_VIDEO = 5;
+    public static final int MEDIA_TYPE_DRM_IMAGE = 6;
     public static final int MEDIA_TYPE_ALL = MEDIA_TYPE_IMAGE | MEDIA_TYPE_VIDEO;
+    //TYPE for Timeline Title
+    public static final int MEDIA_TYPE_TIMELINE_TITLE= 7;
 
     public static final String MEDIA_TYPE_IMAGE_STRING = "image";
     public static final String MEDIA_TYPE_VIDEO_STRING = "video";
@@ -82,6 +87,10 @@
         mDataVersion = version;
     }
 
+    public MediaObject(Path path) {
+        mPath = path;
+    }
+
     public Path getPath() {
         return mPath;
     }
@@ -164,4 +173,12 @@
         }
         throw new IllegalArgumentException();
     }
+
+    /** Some Media Item is not selectable such as Title item in TimeLine. */
+    public boolean isSelectable() {
+        if (getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java
old mode 100644
new mode 100755
index 683aa6b..9d0233e
--- a/src/com/android/gallery3d/data/MediaSet.java
+++ b/src/com/android/gallery3d/data/MediaSet.java
@@ -16,6 +16,7 @@
 
 package com.android.gallery3d.data;
 
+import android.net.Uri;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.util.Future;
 
@@ -42,6 +43,8 @@
     public static final int SYNC_RESULT_CANCELLED = 1;
     public static final int SYNC_RESULT_ERROR = 2;
 
+    private final Object mLock = new Object();
+
     /** Listener to be used with requestSync(SyncListener). */
     public static interface SyncListener {
         /**
@@ -62,6 +65,24 @@
         return 0;
     }
 
+    public int getImageItemCount(){
+      return 0;
+    }
+
+    public int getVideoItemCount(){
+      return 0;
+    }
+
+    /**
+     * Some items is not selectable. such as Title item in TimeLine.
+     * default return {@link #getMediaItemCount()}, override by subclass if need.
+     *
+     * @return total selectable count.
+     */
+    public int getSelectableItemCount() {
+        return getMediaItemCount();
+    }
+
     // Returns the media items in the range [start, start + count).
     //
     // The number of media items returned may be less than the specified count
@@ -87,6 +108,11 @@
         return 0;
     }
 
+    public int getCurrectSize() {
+        // Dummy method, need to be override in implementation classes
+        return 0;
+    }
+
     public MediaSet getSubMediaSet(int index) {
         throw new IndexOutOfBoundsException();
     }
@@ -156,17 +182,23 @@
     // listener is automatically removed when there is no other reference to
     // the listener.
     public void addContentListener(ContentListener listener) {
-        mListeners.put(listener, null);
+        synchronized (mLock) {
+            mListeners.put(listener, null);
+        }
     }
 
     public void removeContentListener(ContentListener listener) {
-        mListeners.remove(listener);
+        synchronized (mLock) {
+            mListeners.remove(listener);
+        }
     }
 
     // This should be called by subclasses when the content is changed.
     public void notifyContentChanged() {
-        for (ContentListener listener : mListeners.keySet()) {
-            listener.onContentDirty();
+        synchronized (mLock) {
+            for (ContentListener listener : mListeners.keySet()) {
+                listener.onContentDirty();
+            }
         }
     }
 
@@ -181,6 +213,11 @@
         return details;
     }
 
+    @Override
+    public Uri getContentUri() {
+        return null;
+    }
+
     // Enumerate all media items in this media set (including the ones in sub
     // media sets), in an efficient order. ItemConsumer.consumer() will be
     // called for each media item with its index.
@@ -222,8 +259,10 @@
         start += enumerateMediaItems(consumer, startIndex);
         int m = getSubMediaSetCount();
         for (int i = 0; i < m; i++) {
-            start += getSubMediaSet(i).enumerateTotalMediaItems(
-                    consumer, startIndex + start);
+            MediaSet set = getSubMediaSet(i);
+            if (set != null) {
+                start += set.enumerateTotalMediaItems(consumer, startIndex + start);
+            }
         }
         return start;
     }
@@ -345,4 +384,24 @@
             if (listener != null) listener.onSyncDone(MediaSet.this, mResult);
         }
     }
+
+    private static boolean sShowTitle = true;
+
+    /**
+     * add for TimelinePage
+     * @param showTitle
+     * true: in TimelinePage we need show TimeTitle
+     * false: we don't need TimeTitle
+     */
+    public static void setShowAlbumsetTimeTitle(boolean showTitle) {
+        sShowTitle = showTitle;
+    }
+
+    /**
+     * @return true: in TimelinePage we need show TimeTitle
+     * false: we don't need TimeTitle
+     */
+    public static boolean isShowAlbumsetTimeTitle() {
+        return sShowTitle;
+    }
 }
diff --git a/src/com/android/gallery3d/data/SizeClustering.java b/src/com/android/gallery3d/data/SizeClustering.java
index b809c84..89c5503 100644
--- a/src/com/android/gallery3d/data/SizeClustering.java
+++ b/src/com/android/gallery3d/data/SizeClustering.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/data/SnailItem.java b/src/com/android/gallery3d/data/SnailItem.java
index 3586d2c..3bb859f 100644
--- a/src/com/android/gallery3d/data/SnailItem.java
+++ b/src/com/android/gallery3d/data/SnailItem.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapRegionDecoder;
+import android.net.Uri;
 
 import com.android.gallery3d.ui.ScreenNail;
 import com.android.gallery3d.util.ThreadPool.Job;
@@ -81,6 +82,11 @@
         return 0;
     }
 
+    @Override
+    public Uri getContentUri() {
+        return null;
+    }
+
     //////////////////////////////////////////////////////////////////////////
     //  Extra methods for SnailItem
     //////////////////////////////////////////////////////////////////////////
diff --git a/src/com/android/gallery3d/data/TagClustering.java b/src/com/android/gallery3d/data/TagClustering.java
index 407ca84..c93c3c9 100644
--- a/src/com/android/gallery3d/data/TagClustering.java
+++ b/src/com/android/gallery3d/data/TagClustering.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 import java.util.Map;
diff --git a/src/com/android/gallery3d/data/TimeClustering.java b/src/com/android/gallery3d/data/TimeClustering.java
index 35cbab1..db47c40 100644
--- a/src/com/android/gallery3d/data/TimeClustering.java
+++ b/src/com/android/gallery3d/data/TimeClustering.java
@@ -98,31 +98,23 @@
 
     @Override
     public void run(MediaSet baseSet) {
-        final int total = baseSet.getTotalMediaItemCount();
-        final SmallItem[] buf = new SmallItem[total];
         final double[] latLng = new double[2];
 
+        final ArrayList<SmallItem> items = new ArrayList<>();
         baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() {
             @Override
             public void consume(int index, MediaItem item) {
-                if (index < 0 || index >= total) return;
                 SmallItem s = new SmallItem();
                 s.path = item.getPath();
+                s.mediaType = item.getMediaType();
                 s.dateInMs = item.getDateInMs();
                 item.getLatLong(latLng);
                 s.lat = latLng[0];
                 s.lng = latLng[1];
-                buf[index] = s;
+                items.add(s);
             }
         });
 
-        ArrayList<SmallItem> items = new ArrayList<SmallItem>(total);
-        for (int i = 0; i < total; i++) {
-            if (buf[i] != null) {
-                items.add(buf[i]);
-            }
-        }
-
         Collections.sort(items, sDateComparator);
 
         int n = items.size();
@@ -189,6 +181,19 @@
         mMaxClusterSize = Utils.clamp(mMaxClusterSize, MIN_MAX_CLUSTER_SIZE, MAX_MAX_CLUSTER_SIZE);
     }
 
+    @Override
+    public int getClusterImageCount(int index) {
+        // TODO Auto-generated method stub
+        return mClusters.get(index).mPhotoCount;
+
+    }
+
+    @Override
+    public int getClusterVideoCount(int index) {
+        // TODO Auto-generated method stub
+        return mClusters.get(index).mVideoCount;
+    }
+
     private void compute(SmallItem currentItem) {
         if (currentItem != null) {
             int numClusters = mClusters.size();
@@ -343,12 +348,15 @@
     Path path;
     long dateInMs;
     double lat, lng;
+    int mediaType;
 }
 
 class Cluster {
     @SuppressWarnings("unused")
     private static final String TAG = "Cluster";
     private static final String MMDDYY_FORMAT = "MMddyy";
+    public int mPhotoCount = 0;
+    public int mVideoCount = 0;
 
     // This is for TimeClustering only.
     public boolean mGeographicallySeparatedFromPrevCluster = false;
@@ -359,6 +367,11 @@
     }
 
     public void addItem(SmallItem item) {
+        if(item.mediaType == MediaObject.MEDIA_TYPE_IMAGE) {
+            mPhotoCount++;
+        } else if(item.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
+           mVideoCount++;
+        }
         mItems.add(item);
     }
 
diff --git a/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
new file mode 100755
index 0000000..b3b91bb
--- /dev/null
+++ b/src/com/android/gallery3d/data/TimeLineTitleMediaItem.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.data;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapRegionDecoder;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.ui.TimeLineTitleMaker;
+import com.android.gallery3d.util.GalleryUtils;
+import com.android.gallery3d.util.ThreadPool.Job;
+
+public class TimeLineTitleMediaItem extends MediaItem {
+    private static final String TAG = "TimeLineTitleMediaItem";
+    private String mTitle;
+    private int mPhotoCount;
+    private int mVideoCount;
+
+    public TimeLineTitleMediaItem(Path path) {
+        super(path);
+    }
+
+
+    public Job<Bitmap> requestTitle(int type, TimeLineTitleMaker maker) {
+        if (maker != null) {
+            return maker.requestTimeLineTitle(mTitle, mPhotoCount, mVideoCount);
+        }
+        return null;
+    }
+
+    public void setTitle(String title) {
+        mTitle = title;
+    }
+    public Job<Bitmap> requestImage(int type) {
+        return null;
+    }
+
+    public Job<BitmapRegionDecoder> requestLargeImage() {
+        Log.e(TAG, "Operation not supported");
+        return null;
+    }
+
+    public String getMimeType() {
+        return MediaObject.MEDIA_TYPE_IMAGE_STRING;
+    }
+
+    @Override
+    public int getMediaType() {
+        return MediaObject.MEDIA_TYPE_TIMELINE_TITLE;
+    }
+
+    public void setImageCount(int images) {
+        mPhotoCount = images;
+    }
+
+    public void setVideoCount(int video) {
+        mVideoCount = video;
+    }
+
+    public int getWidth() {
+        return 0;
+    }
+
+    public int getHeight() {
+        return 0;
+    }
+
+}
diff --git a/src/com/android/gallery3d/data/UnlockImage.java b/src/com/android/gallery3d/data/UnlockImage.java
index ed3b485..02fa464 100644
--- a/src/com/android/gallery3d/data/UnlockImage.java
+++ b/src/com/android/gallery3d/data/UnlockImage.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.data;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 
 public class UnlockImage extends ActionImage {
diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java
index b3fe1de..47ba535 100644
--- a/src/com/android/gallery3d/data/UriImage.java
+++ b/src/com/android/gallery3d/data/UriImage.java
@@ -17,6 +17,7 @@
 package com.android.gallery3d.data;
 
 import android.content.ContentResolver;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory.Options;
@@ -58,12 +59,14 @@
     private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this);
 
     private GalleryApp mApplication;
+//    private String mFilePath;
 
     public UriImage(GalleryApp application, Path path, Uri uri, String contentType) {
         super(path, nextVersionNumber());
         mUri = uri;
         mApplication = Utils.checkNotNull(application);
         mContentType = contentType;
+//        mFilePath = DrmHelper.getFilePath(mApplication.getAndroidContext(), uri);
     }
 
     @Override
@@ -171,6 +174,14 @@
     private class RegionDecoderJob implements Job<BitmapRegionDecoder> {
         @Override
         public BitmapRegionDecoder run(JobContext jc) {
+//            if (DrmHelper.isDrmFile(getFilePath())) {
+//                BitmapRegionDecoder decoder = DrmHelper
+//                        .createBitmapRegionDecoder(getFilePath(), false);
+//                mWidth = decoder.getWidth();
+//                mHeight = decoder.getHeight();
+//                return decoder;
+//            }
+
             if (!prepareInputFile(jc)) return null;
             BitmapRegionDecoder decoder = DecodeUtils.createBitmapRegionDecoder(
                     jc, mFileDescriptor.getFileDescriptor(), false);
@@ -189,6 +200,10 @@
 
         @Override
         public Bitmap run(JobContext jc) {
+//            if (DrmHelper.isDrmFile(getFilePath())) {
+//                return DecodeUtils.ensureGLCompatibleBitmap(DrmHelper.getBitmap(getFilePath()));
+//            }
+
             if (!prepareInputFile(jc)) return null;
             int targetSize = MediaItem.getTargetSize(mType);
             Options options = new Options();
@@ -211,11 +226,19 @@
 
     @Override
     public int getSupportedOperations() {
-        int supported = SUPPORT_PRINT | SUPPORT_SETAS;
-        if (isSharable()) supported |= SUPPORT_SHARE;
-        if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) {
-            supported |= SUPPORT_EDIT | SUPPORT_FULL_IMAGE;
-        }
+        int supported = 0;
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            supported |= SUPPORT_DRM_INFO | SUPPORT_FULL_IMAGE;
+//            if (DrmHelper.isShareableDrmFile(getFilePath())) {
+//                supported |= SUPPORT_SHARE;
+//            }
+//        } else {
+            supported = SUPPORT_PRINT | SUPPORT_SETAS;
+            if (isSharable()) supported |= SUPPORT_SHARE;
+            if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) {
+                supported |= SUPPORT_EDIT | SUPPORT_FULL_IMAGE;
+            }
+//        }
         return supported;
     }
 
@@ -239,6 +262,10 @@
 
     @Override
     public int getMediaType() {
+//        if (DrmHelper.isDrmFile(getFilePath())) {
+//            return MEDIA_TYPE_DRM_IMAGE;
+//        }
+
         return MEDIA_TYPE_IMAGE;
     }
 
@@ -295,4 +322,9 @@
     public int getRotation() {
         return mRotation;
     }
+
+//    @Override
+//    public String getFilePath() {
+//        return mFilePath;
+//    }
 }
diff --git a/src/com/android/gallery3d/data/UriSource.java b/src/com/android/gallery3d/data/UriSource.java
index f66bacd..f31283c 100644
--- a/src/com/android/gallery3d/data/UriSource.java
+++ b/src/com/android/gallery3d/data/UriSource.java
@@ -17,7 +17,9 @@
 package com.android.gallery3d.data;
 
 import android.content.ContentResolver;
+//import android.drm.DrmHelper;
 import android.net.Uri;
+import android.text.TextUtils;
 import android.webkit.MimeTypeMap;
 
 import com.android.gallery3d.app.GalleryApp;
@@ -73,6 +75,19 @@
     @Override
     public Path findPathByUri(Uri uri, String type) {
         String mimeType = getMimeType(uri);
+//        if (DrmHelper.isDrmMimeType(mimeType)) {
+//            String path = DrmHelper.getFilePath(
+//                    mApplication.getAndroidContext(), uri);
+//            if (!TextUtils.isEmpty(path)) {
+//                try {
+//                    return Path.fromString("/uri/"
+//                            + URLEncoder.encode(path, CHARSET_UTF_8) + "/"
+//                            + URLEncoder.encode(type, CHARSET_UTF_8));
+//                } catch (UnsupportedEncodingException e) {
+//                    throw new AssertionError(e);
+//                }
+//            }
+//        }
 
         // Try to find a most specific type but it has to be started with "image/"
         if ((type == null) || (IMAGE_TYPE_ANY.equals(type)
diff --git a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java b/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java
index bc9342d..c792c2c 100644
--- a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java
+++ b/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java
@@ -23,7 +23,7 @@
 import android.util.TypedValue;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class CenteredLinearLayout extends LinearLayout {
     private final int mMaxWidth;
diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
index 95fc56d..86cc870 100644
--- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
+++ b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java
@@ -66,7 +66,8 @@
     }
 
     public void hide() {
-        mContainer.setVisibility(View.GONE);
+        if(mContainer != null)
+            mContainer.setVisibility(View.GONE);
     }
 
     public void hideOldViews() {
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
old mode 100644
new mode 100755
index d0bc29a..a9a1715
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -16,96 +16,126 @@
 
 package com.android.gallery3d.filtershow;
 
+import java.io.File;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Locale;
+import java.util.Vector;
+
 import android.app.ActionBar;
 import android.app.AlertDialog;
 import android.app.ProgressDialog;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
+import android.provider.MediaStore;
 import androidx.fragment.app.DialogFragment;
 import androidx.fragment.app.Fragment;
-import androidx.fragment.app.FragmentActivity;
 import androidx.fragment.app.FragmentTransaction;
 import androidx.print.PrintHelper;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.TypedValue;
+import android.view.Gravity;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.View.OnTouchListener;
 import android.view.ViewPropertyAnimator;
+import android.view.Window;
 import android.view.WindowManager;
+import android.webkit.MimeTypeMap;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
+import android.widget.Button;
+import android.widget.EditText;
 import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
 import android.widget.PopupMenu;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
-import android.widget.Spinner;
+import android.widget.RelativeLayout;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.AbstractPermissionActivity;
 import com.android.gallery3d.app.PhotoPage;
 import com.android.gallery3d.data.LocalAlbum;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.category.Action;
 import com.android.gallery3d.filtershow.category.CategoryAdapter;
-import com.android.gallery3d.filtershow.category.CategorySelected;
+import com.android.gallery3d.filtershow.category.CategoryPanelLevelTwo;
 import com.android.gallery3d.filtershow.category.CategoryView;
+import com.android.gallery3d.filtershow.category.EditorCropPanel;
 import com.android.gallery3d.filtershow.category.MainPanel;
+import com.android.gallery3d.filtershow.category.StraightenPanel;
 import com.android.gallery3d.filtershow.category.SwipableView;
+import com.android.gallery3d.filtershow.category.TruePortraitMaskEditorPanel;
+import com.android.gallery3d.filtershow.category.TrueScannerPanel;
+import com.android.gallery3d.filtershow.data.FilterPresetSource;
+import com.android.gallery3d.filtershow.data.FilterPresetSource.SaveOption;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
 import com.android.gallery3d.filtershow.data.UserPresetsManager;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
 import com.android.gallery3d.filtershow.editors.Editor;
-import com.android.gallery3d.filtershow.editors.EditorChanSat;
-import com.android.gallery3d.filtershow.editors.EditorColorBorder;
 import com.android.gallery3d.filtershow.editors.EditorCrop;
-import com.android.gallery3d.filtershow.editors.EditorDraw;
-import com.android.gallery3d.filtershow.editors.EditorGrad;
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
 import com.android.gallery3d.filtershow.editors.EditorManager;
-import com.android.gallery3d.filtershow.editors.EditorMirror;
 import com.android.gallery3d.filtershow.editors.EditorPanel;
-import com.android.gallery3d.filtershow.editors.EditorRedEye;
-import com.android.gallery3d.filtershow.editors.EditorRotate;
 import com.android.gallery3d.filtershow.editors.EditorStraighten;
-import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitFusion;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitImageOnly;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitMask;
+import com.android.gallery3d.filtershow.editors.HazeBusterEditor;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
-import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
+import com.android.gallery3d.filtershow.editors.SeeStraightEditor;
+import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
-import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
+import com.android.gallery3d.filtershow.filters.SaveWaterMark;
+import com.android.gallery3d.filtershow.filters.SimpleMakeupImageFilter;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
 import com.android.gallery3d.filtershow.history.HistoryItem;
 import com.android.gallery3d.filtershow.history.HistoryManager;
 import com.android.gallery3d.filtershow.imageshow.ImageShow;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.imageshow.Spline;
 import com.android.gallery3d.filtershow.info.InfoPanel;
+import com.android.gallery3d.filtershow.mediapicker.MediaPickerFragment;
 import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 import com.android.gallery3d.filtershow.pipeline.ProcessingService;
@@ -113,24 +143,23 @@
 import com.android.gallery3d.filtershow.presets.UserPresetsAdapter;
 import com.android.gallery3d.filtershow.provider.SharedImageProvider;
 import com.android.gallery3d.filtershow.state.StateAdapter;
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
+import com.android.gallery3d.filtershow.tools.FilterGeneratorNativeEngine;
 import com.android.gallery3d.filtershow.tools.SaveImage;
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
 import com.android.gallery3d.filtershow.tools.XmpPresets;
 import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults;
 import com.android.gallery3d.filtershow.ui.ExportDialog;
 import com.android.gallery3d.filtershow.ui.FramedTextButton;
 import com.android.gallery3d.util.GalleryUtils;
 import com.android.photos.data.GalleryBitmapPool;
+import com.thundersoft.hz.selfportrait.detect.FaceDetect;
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
 
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Vector;
-
-public class FilterShowActivity extends FragmentActivity implements OnItemClickListener,
-        OnShareTargetSelectedListener, DialogInterface.OnShowListener,
-        DialogInterface.OnDismissListener, PopupMenu.OnDismissListener{
+public class FilterShowActivity extends AbstractPermissionActivity implements OnItemClickListener,
+        DialogInterface.OnShowListener,
+        DialogInterface.OnDismissListener, PopupMenu.OnDismissListener {
 
     private String mAction = "";
     MasterImage mMasterImage = null;
@@ -139,7 +168,6 @@
 
     public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET";
     public static final String LAUNCH_FULLSCREEN = "launch-fullscreen";
-    public static final boolean RESET_TO_LOADED = false;
     private ImageShow mImageShow = null;
 
     private View mSaveButton = null;
@@ -147,16 +175,19 @@
     private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this);
     private Editor mCurrentEditor = null;
 
+    private MediaPickerFragment mMediaPicker;
+
     private static final int SELECT_PICTURE = 1;
+    public static final int SELECT_FUSION_UNDERLAY = 2;
     private static final String LOGTAG = "FilterShowActivity";
 
     private boolean mShowingTinyPlanet = false;
     private boolean mShowingImageStatePanel = false;
     private boolean mShowingVersionsPanel = false;
+    private boolean mShowingFilterGenerator = false;
 
     private final Vector<ImageShow> mImageViews = new Vector<ImageShow>();
 
-    private ShareActionProvider mShareActionProvider;
     private File mSharedOutputFile = null;
 
     private boolean mSharingImage = false;
@@ -164,6 +195,9 @@
     private WeakReference<ProgressDialog> mSavingProgressDialog;
 
     private LoadBitmapTask mLoadBitmapTask;
+    private LoadHighresBitmapTask mHiResBitmapTask;
+    private ParseDepthMapTask mParseDepthMapTask;
+    private LoadTruePortraitTask mLoadTruePortraitTask;
 
     private Uri mOriginalImageUri = null;
     private ImagePreset mOriginalPreset = null;
@@ -177,7 +211,15 @@
     private CategoryAdapter mCategoryBordersAdapter = null;
     private CategoryAdapter mCategoryGeometryAdapter = null;
     private CategoryAdapter mCategoryFiltersAdapter = null;
+    private CategoryAdapter mCategoryTrueScannerAdapter = null;
+    private CategoryAdapter mCategoryHazeBusterAdapter = null;
+    private CategoryAdapter mCategorySeeStraightAdapter = null;
     private CategoryAdapter mCategoryVersionsAdapter = null;
+    private CategoryAdapter mCategoryMakeupAdapter = null;
+    private CategoryAdapter mCategoryDualCamAdapter = null;
+    private CategoryAdapter mCategoryTruePortraitAdapter = null;
+    private CategoryAdapter mCategoryFilterPresetAdapter = null;
+    private ArrayList<CategoryAdapter> mCategoryWatermarkAdapters;
     private int mCurrentPanel = MainPanel.LOOKS;
     private Vector<FilterUserPresetRepresentation> mVersions =
             new Vector<FilterUserPresetRepresentation>();
@@ -194,7 +236,41 @@
     private Menu mMenu;
     private DialogInterface mCurrentDialog = null;
     private PopupMenu mCurrentMenu = null;
-    private boolean mLoadingVisible = true;
+    private boolean mReleaseDualCam = false;
+    private ImageButton imgComparison;
+    private String mPopUpText, mCancel;
+    RelativeLayout rlImageContainer;
+    private int mEditrCropButtonSelect = 0;
+    private boolean isComingFromEditorScreen;
+    private boolean mIsReloadByConfigurationChanged;
+    private AlertDialog.Builder mBackAlertDialogBuilder;
+
+    private ProgressDialog mLoadingDialog;
+    private long mRequestId = -1;
+    private WaterMarkView mWaterMarkView;
+    private boolean hasWaterMark;
+    private String locationStr;
+    private String temperature;
+    protected Handler handler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case SaveWaterMark.MARK_SAVE_COMPLETE:
+                    completeSaveImage((Uri) msg.obj);
+                    break;
+                default:
+                    break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+    private SaveWaterMark mSaveWaterMark = new SaveWaterMark();
+
+    private PresetManagementDialog mPresetDialog;
+    private FilterPresetSource mFilterPresetSource;
+    private ArrayList <SaveOption>  tempFilterArray = new ArrayList<SaveOption>();
+    private boolean mChangeable = false;
+    private int mOrientation;
 
     public ProcessingService getProcessingService() {
         return mBoundService;
@@ -204,6 +280,39 @@
         return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction);
     }
 
+    public long getRequestId() {
+        return mRequestId;
+    }
+
+    private void registerFilter() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ProcessingService.SAVE_IMAGE_COMPLETE_ACTION);
+        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
+        registerReceiver(mHandlerReceiver, filter);
+    }
+
+    private final BroadcastReceiver mHandlerReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (ProcessingService.SAVE_IMAGE_COMPLETE_ACTION.equals(action)) {
+                Bundle bundle = intent.getExtras();
+                long requestId = bundle.getLong(ProcessingService.KEY_REQUEST_ID);
+                //only handle own request
+                if (requestId == mRequestId) {
+                    String url = bundle.getString(ProcessingService.KEY_URL);
+                    Uri saveUri = url == null ? null : Uri.parse(url);
+                    completeSaveImage(saveUri);
+                }
+            } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+                FiltersManager.reset();
+                getProcessingService().setupPipeline();
+                fillCategories();
+            }
+        }
+    };
+
+    private boolean canUpdataUI = false;
     private ServiceConnection mConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
@@ -215,8 +324,7 @@
              * cast its IBinder to a concrete class and directly access it.
              */
             mBoundService = ((ProcessingService.LocalBinder)service).getService();
-            mBoundService.setFiltershowActivity(FilterShowActivity.this);
-            mBoundService.onStart();
+            updateUIAfterServiceStarted();
         }
 
         @Override
@@ -228,6 +336,8 @@
              * see this happen.
              */
             mBoundService = null;
+            ImageFilter.resetStatics();
+            MasterImage.setMaster(null);
         }
     };
 
@@ -252,6 +362,13 @@
     }
 
     public void updateUIAfterServiceStarted() {
+        if (!isPermissionGranted()) {
+            canUpdataUI = true;
+            return;
+        }
+        //This activity will have more than one running instances
+        //mRequestId to distinguish the different instance's request
+        mRequestId = System.currentTimeMillis();
         MasterImage.setMaster(mMasterImage);
         ImageFilter.setActivityForMemoryToasts(this);
         mUserPresetsManager = new UserPresetsManager(this);
@@ -260,7 +377,6 @@
         setupMasterImage();
         setupMenu();
         setDefaultValues();
-        fillEditors();
         getWindow().setBackgroundDrawable(new ColorDrawable(0));
         loadXML();
 
@@ -273,16 +389,21 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
+        mOrientation = getResources().getConfiguration().orientation;
         boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait);
         if (onlyUsePortrait) {
             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
         }
 
         clearGalleryBitmapPool();
+        registerFilter();
         doBindService();
         getWindow().setBackgroundDrawable(new ColorDrawable(Color.GRAY));
         setContentView(R.layout.filtershow_splashscreen);
+        Window win = getWindow();
+        WindowManager.LayoutParams winParams = win.getAttributes();
+        winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
+        win.setAttributes(winParams);
     }
 
     public boolean isShowingImageStatePanel() {
@@ -294,27 +415,112 @@
             return;
         }
         MainPanel panel = new MainPanel();
+        Bundle bundle = new Bundle();
+        bundle.putBoolean(MainPanel.EDITOR_TAG, isComingFromEditorScreen);
+        panel.setArguments(bundle);
+        isComingFromEditorScreen = false;
         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
         transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
         transaction.commitAllowingStateLoss();
     }
 
-    public void loadEditorPanel(FilterRepresentation representation,
-                                final Editor currentEditor) {
-        if (representation.getEditorId() == ImageOnlyEditor.ID) {
-            currentEditor.reflectCurrentFilter();
+    public void loadEditorPanel(final FilterRepresentation representation) {
+        final int currentId = representation.getEditorId();
+
+        // show representation
+        if (mCurrentEditor != null) {
+            mCurrentEditor.detach();
+        }
+        mCurrentEditor = mEditorPlaceHolder.showEditor(currentId);
+
+        if (mCurrentEditor.showsActionBar()) {
+            setActionBar();
+            showActionBar(true);
+        }
+
+        if (representation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+            loadWaterMarkPanel((FilterWatermarkRepresentation) representation);
             return;
         }
-        final int currentId = currentEditor.getID();
+
+        if (currentId == ImageOnlyEditor.ID) {
+            mCurrentEditor.reflectCurrentFilter();
+            return;
+        }
+        if (currentId == EditorTruePortraitImageOnly.ID) {
+            mCurrentEditor.reflectCurrentFilter();
+            setActionBarForEffects(mCurrentEditor);
+            return;
+        }
+        if (currentId == EditorCrop.ID) {
+            loadEditorCropPanel();
+            return;
+        }
+        if (useStraightenPanel(currentId)) {
+            new Runnable() {
+                @Override
+                public void run() {
+                    StraightenPanel panel = new StraightenPanel();
+                    Bundle bundle = new Bundle();
+                    bundle.putInt(StraightenPanel.EDITOR_ID, currentId);
+                    bundle.putString(StraightenPanel.EDITOR_NAME, representation.getName());
+                    panel.setArguments(bundle);
+                    FragmentTransaction transaction =
+                            getSupportFragmentManager().beginTransaction();
+                    transaction.remove(getSupportFragmentManager().findFragmentByTag(
+                            MainPanel.FRAGMENT_TAG));
+                    transaction.replace(R.id.main_panel_container, panel,
+                            MainPanel.FRAGMENT_TAG);
+                    transaction.commit();
+                }
+            }.run();
+            return;
+        }
+        if (currentId == TrueScannerEditor.ID) {
+            new Runnable() {
+                @Override
+                public void run() {
+                    TrueScannerPanel panel = new TrueScannerPanel();
+                    FragmentTransaction transaction =
+                            getSupportFragmentManager().beginTransaction();
+                    transaction.remove(getSupportFragmentManager().findFragmentByTag(
+                            MainPanel.FRAGMENT_TAG));
+                    transaction.replace(R.id.main_panel_container, panel,
+                            MainPanel.FRAGMENT_TAG);
+                    transaction.commit();
+                }
+            }.run();
+            return;
+        }
+        if(currentId == EditorTruePortraitMask.ID) {
+            new Runnable() {
+                @Override
+                public void run() {
+                    setActionBarForEffects(mCurrentEditor);
+                    TruePortraitMaskEditorPanel panel = new TruePortraitMaskEditorPanel();
+                    FragmentTransaction transaction =
+                            getSupportFragmentManager().beginTransaction();
+                    transaction.remove(getSupportFragmentManager().findFragmentByTag(
+                            MainPanel.FRAGMENT_TAG));
+                    transaction.replace(R.id.main_panel_container, panel,
+                            MainPanel.FRAGMENT_TAG);
+                    transaction.commit();
+                }
+            }.run();
+            return;
+        }
+
         Runnable showEditor = new Runnable() {
             @Override
             public void run() {
                 EditorPanel panel = new EditorPanel();
                 panel.setEditor(currentId);
-                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG));
-                transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG);
-                transaction.commit();
+                setActionBarForEffects(mCurrentEditor);
+                Fragment main =
+                        getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+                if (main instanceof MainPanel) {
+                    ((MainPanel) main).setEditorPanelFragment(panel);
+                }
             }
         };
         Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
@@ -337,6 +543,69 @@
         }
     }
 
+    private boolean useStraightenPanel(int EditorID) {
+        return (EditorID == EditorStraighten.ID || EditorID == HazeBusterEditor.ID || EditorID == SeeStraightEditor.ID);
+    }
+
+    private void loadEditorCropPanel() {
+        new Runnable() {
+            @Override
+            public void run() {
+                EditorCropPanel panel = new EditorCropPanel();
+                FragmentTransaction transaction =
+                        getSupportFragmentManager().beginTransaction();
+                transaction.remove(getSupportFragmentManager().findFragmentByTag(
+                        MainPanel.FRAGMENT_TAG));
+                transaction.replace(R.id.main_panel_container, panel,
+                        MainPanel.FRAGMENT_TAG);
+                transaction.commitAllowingStateLoss();
+            }
+        }.run();
+    }
+
+    private void loadWaterMarkPanel(final FilterWatermarkRepresentation representation) {
+        new Runnable() {
+            @Override
+            public void run() {
+                CategoryPanelLevelTwo panel = new CategoryPanelLevelTwo(representation.getAdapterId());
+                FragmentTransaction transaction =
+                        getSupportFragmentManager().beginTransaction();
+                transaction.remove(getSupportFragmentManager().findFragmentByTag(
+                        MainPanel.FRAGMENT_TAG));
+                transaction.replace(R.id.main_panel_container, panel,
+                        MainPanel.FRAGMENT_TAG);
+                transaction.commitAllowingStateLoss();
+            }
+        }.run();
+    }
+
+    public void setLocation(String location) {
+        locationStr = location;
+    }
+
+    public void setTemperature(String temperature) {
+        this.temperature = temperature;
+    }
+
+    public void leaveSeekBarPanel() {
+        removeSeekBarPanel();
+        showDefaultImageView();
+        setActionBar();
+        showActionBar(true);
+    }
+
+    private void removeSeekBarPanel() {
+        Fragment currentPanel =
+                getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+        if (currentPanel instanceof MainPanel) {
+            ((MainPanel) currentPanel).removeEditorPanelFragment();
+            if (mCurrentEditor != null) {
+                mCurrentEditor.detach();
+            }
+            mCurrentEditor = null;
+        }
+    }
+
     public void toggleInformationPanel() {
         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
         transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
@@ -347,20 +616,15 @@
 
     private void loadXML() {
         setContentView(R.layout.filtershow_activity);
-
-        ActionBar actionBar = getActionBar();
-        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
-        actionBar.setCustomView(R.layout.filtershow_actionbar);
-        actionBar.setBackgroundDrawable(new ColorDrawable(
-                getResources().getColor(R.color.background_screen)));
-
-        mSaveButton = actionBar.getCustomView();
-        mSaveButton.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                saveImage();
-            }
-        });
+        Resources r = getResources();
+        setActionBar();
+        mPopUpText = r.getString(R.string.discard).toUpperCase(
+                Locale.getDefault());
+        mCancel = r.getString(R.string.cancel).toUpperCase(Locale.getDefault());
+        int marginTop = r.getDimensionPixelSize(R.dimen.compare_margin_top);
+        int marginRight = r.getDimensionPixelSize(R.dimen.compare_margin_right);
+        imgComparison = (ImageButton) findViewById(R.id.imgComparison);
+        rlImageContainer = (RelativeLayout) findViewById(R.id.imageContainer);
 
         mImageShow = (ImageShow) findViewById(R.id.imageShow);
         mImageViews.add(mImageShow);
@@ -371,6 +635,175 @@
         mImageShow.attach();
 
         setupStatePanel();
+
+        imgComparison.setOnTouchListener(new OnTouchListener() {
+
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                int action = event.getAction();
+                action = action & MotionEvent.ACTION_MASK;
+                if (action == MotionEvent.ACTION_DOWN) {
+                    MasterImage.getImage().setShowsOriginal(true);
+                    v.setPressed(true);
+                    if (mWaterMarkView != null) {
+                        mWaterMarkView.setVisibility(View.GONE);
+                    }
+                }
+                if (action == MotionEvent.ACTION_UP
+                        || action == MotionEvent.ACTION_CANCEL
+                        || action == MotionEvent.ACTION_OUTSIDE) {
+                    v.setPressed(false);
+                    MasterImage.getImage().setShowsOriginal(false);
+                    if (mWaterMarkView != null) {
+                        mWaterMarkView.setVisibility(View.VISIBLE);
+                    }
+                }
+
+                return false;
+            }
+        });
+    }
+
+    public void toggleComparisonButtonVisibility() {
+        if (imgComparison.getVisibility() == View.VISIBLE)
+            imgComparison.setVisibility(View.GONE);
+    }
+
+    private void showSaveButtonIfNeed() {
+        if (MasterImage.getImage().hasModifications()) {
+            mSaveButton.setVisibility(View.VISIBLE);
+        } else {
+            mSaveButton.setVisibility(View.GONE);
+        }
+    }
+
+    public void setActionBar() {
+        ActionBar actionBar = getActionBar();
+        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+        actionBar.setBackgroundDrawable(new ColorDrawable(getResources()
+                .getColor(R.color.edit_actionbar_background)));
+        ActionBar.LayoutParams lp = new ActionBar.LayoutParams(
+                ActionBar.LayoutParams.MATCH_PARENT,
+                ActionBar.LayoutParams.MATCH_PARENT,
+                Gravity.CENTER);
+        View customView = getLayoutInflater().inflate(R.layout.filtershow_actionbar, null);
+        actionBar.setCustomView(customView, lp);
+        mSaveButton = actionBar.getCustomView().findViewById(R.id.filtershow_done);
+        mSaveButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                saveImage();
+            }
+        });
+
+        showSaveButtonIfNeed();
+
+        View exitButton = actionBar.getCustomView().findViewById(R.id.filtershow_exit);
+        exitButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mImageShow.hasModifications()) {
+                    if (mBackAlertDialogBuilder == null) {
+                        createBackDialog();
+                    }
+                    mBackAlertDialogBuilder.show();
+                } else {
+                    done();
+                }
+            }
+        });
+
+        invalidateOptionsMenu();
+    }
+
+    public void setActionBarForEffects(final Editor currentEditor) {
+        ActionBar actionBar = getActionBar();
+        actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+        actionBar.setBackgroundDrawable(new ColorDrawable(getResources()
+                .getColor(R.color.edit_actionbar_background)));
+        actionBar.setCustomView(R.layout.filtershow_actionbar_effects);
+        ImageButton cancelButton = (ImageButton) actionBar.getCustomView()
+                .findViewById(R.id.cancelFilter);
+        ImageButton applyButton = (ImageButton) actionBar.getCustomView()
+                .findViewById(R.id.applyFilter);
+        Button editTitle = (Button) actionBar.getCustomView().findViewById(
+                R.id.applyEffect);
+        editTitle.setTransformationMethod(null);
+        View actionControl = actionBar.getCustomView().findViewById(
+                R.id.panelAccessoryViewList);
+        cancelButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                cancelCurrentFilter();
+                FilterShowActivity.this.backToMain();
+                setActionBar();
+            }
+        });
+        applyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                currentEditor.finalApplyCalled();
+                FilterShowActivity.this.backToMain();
+                setActionBar();
+            }
+        });
+
+        if (currentEditor != null) {
+            if(!currentEditor.showsActionBarControls()) {
+                cancelButton.setVisibility(View.GONE);
+                applyButton.setVisibility(View.GONE);
+            }
+            currentEditor.setEditorTitle(editTitle);
+            currentEditor.reflectCurrentFilter();
+            if (currentEditor.useUtilityPanel()) {
+                currentEditor.openUtilityPanel((LinearLayout) actionControl);
+            }
+        }
+    }
+
+    private void showActionBar(boolean show) {
+        ActionBar actionBar = getActionBar();
+        if (actionBar != null ) {
+            if (show) {
+                if (!actionBar.isShowing()) {
+                    actionBar.show();
+                }
+            } else {
+                if (actionBar.isShowing()) {
+                    actionBar.hide();
+                }
+            }
+        }
+    }
+
+    public void cancelCurrentFilter() {
+        MasterImage masterImage = MasterImage.getImage();
+        HistoryManager adapter = masterImage.getHistory();
+
+        int position = adapter.undo();
+        masterImage.onHistoryItemClick(position);
+        invalidateViews();
+
+        if(!masterImage.hasFusionApplied()) {
+            masterImage.setFusionUnderlay(null);
+            masterImage.setScaleFactor(1);
+            masterImage.resetTranslation();
+        }
+        clearWaterMark();
+    }
+
+    public void adjustCompareButton(boolean scaled) {
+        if (imgComparison == null) {
+            return;
+        }
+        Resources r = getResources();
+        int marginTop, marginRight;
+        marginTop = r.getDimensionPixelSize(R.dimen.compare_margin_top);
+        marginRight = r.getDimensionPixelSize(R.dimen.compare_margin_right);
+        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) imgComparison
+                .getLayoutParams();
+        params.setMargins(0, marginTop, marginRight, 0);
+        imgComparison.setLayoutParams(params);
     }
 
     public void fillCategories() {
@@ -379,7 +812,14 @@
         fillBorders();
         fillTools();
         fillEffects();
+        fillTrueScanner();
+        fillHazeBuster();
+        fillSeeStraight();
         fillVersions();
+        fillMakeup();
+        fillDualCamera();
+        fillTruePortrait();
+        fillWaterMarks();
     }
 
     public void setupStatePanel() {
@@ -451,6 +891,136 @@
         }
         mUserPresetsManager.delete(rep.getId());
         updateUserPresetsFromManager();
+     }
+
+    public void handlePreset(Action action,View view,int i) {
+        mChangeable = true;
+        mHandledSwipeView = view;
+        final Action ac = action;
+        mFilterPresetSource = new FilterPresetSource(this);
+        switch (i) {
+            case R.id.renameButton:
+                final View layout = View.inflate(this,R.layout.filtershow_default_edittext,null);
+                AlertDialog.Builder renameAlertDialogBuilder = new AlertDialog.Builder(this);
+                renameAlertDialogBuilder.setTitle(R.string.rename_before_exit);
+                renameAlertDialogBuilder.setView(layout);
+                renameAlertDialogBuilder.setPositiveButton(R.string.ok,
+                        new DialogInterface.OnClickListener(){
+                            @Override
+                            public void onClick(DialogInterface dialog, int id){
+                                EditText mEditText = (EditText) layout.findViewById(
+                                        R.id.filtershow_default_edit);
+                                String name = String.valueOf(mEditText.getText());
+                                if ( (name.trim().length() == 0)|| name.isEmpty()) {
+                                    Toast.makeText(getApplicationContext(),
+                                            getString(R.string.filter_name_notification),
+                                            Toast.LENGTH_SHORT).show();
+                                } else if (isDuplicateName(name)) {
+                                    Toast.makeText(getApplicationContext(),
+                                            getString(R.string.filter_name_duplicate),
+                                            Toast.LENGTH_SHORT).show();
+                                } else {
+                                    renamePreset(ac, name);
+                                }
+                                dialog.dismiss();
+                            }
+                        }
+                );
+                renameAlertDialogBuilder.setNegativeButton(mCancel,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick (DialogInterface dialog, int id){
+
+                            }
+                        }
+                );
+                renameAlertDialogBuilder.create().show();
+                break;
+
+            case R.id.deleteButton:
+                String name = action.getName();
+                AlertDialog.Builder deleteAlertDialogBuilder = new AlertDialog.Builder(this);
+                String textview ="Do you want to delete "+name+"?";
+                deleteAlertDialogBuilder.setMessage(textview)
+                        .setTitle(R.string.delete_before_exit);
+                deleteAlertDialogBuilder.setPositiveButton(R.string.ok,
+                        new DialogInterface.OnClickListener(){
+                            @Override
+                            public void onClick(DialogInterface dialog, int id){
+                                ((SwipableView) mHandledSwipeView).delete();
+                                dialog.dismiss();
+                            }
+                        }
+                );
+                deleteAlertDialogBuilder.setNegativeButton(mCancel,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick (DialogInterface dialog, int id){
+                                dialog.dismiss();
+
+                            }
+                        }
+                );
+                deleteAlertDialogBuilder.create().show();
+                break;
+        }
+    }
+
+    public void removePreset(Action action) {
+        FilterPresetRepresentation rep =
+                (FilterPresetRepresentation)action.getRepresentation();
+        if (rep == null) {
+            return;
+        }
+        if (tempFilterArray.size() != 0) {
+            for (int i = 0; i < tempFilterArray.size(); i++) {
+                if (rep.getId() == tempFilterArray.get(i)._id) {
+                    tempFilterArray.remove(i);
+                    fillLooks();
+                    return;
+                }
+            }
+        }
+        mFilterPresetSource.removePreset(rep.getId());
+        fillLooks();
+    }
+
+    public void renamePreset(Action action, String name) {
+        FilterPresetRepresentation rep =
+                (FilterPresetRepresentation)action.getRepresentation();
+        if (rep == null) {
+            return;
+        }
+        if (tempFilterArray.size() != 0) {
+            for (int i = 0; i < tempFilterArray.size(); i++) {
+                if (rep.getId() == tempFilterArray.get(i)._id) {
+                    tempFilterArray.get(i).name = name;
+                    fillLooks();
+                    return;
+                }
+            }
+        }
+        mFilterPresetSource.updatePresetName(rep.getId(),name);
+        fillLooks();
+    }
+
+    public boolean isDuplicateName(String name) {
+        ArrayList<String> nameSum = new ArrayList<String>();
+        if (tempFilterArray.size() != 0) {
+            for (int i = 0; i < tempFilterArray.size(); i++)
+                nameSum.add(tempFilterArray.get(i).name);
+        }
+
+        ArrayList<SaveOption> ret = mFilterPresetSource.getAllUserPresets();
+        if (ret != null) {
+            for (int id = 0; id < ret.size(); id++)
+                nameSum.add(ret.get(id).name);
+        }
+
+        for (int i = 0; i < nameSum.size(); i++) {
+            if (name.equals(nameSum.get(i))) return true;
+        }
+        return false;
     }
 
     private void fillEffects() {
@@ -468,6 +1038,135 @@
         }
     }
 
+    private void fillMakeup() {
+        if(!SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
+            return;
+        }
+
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> makeups = filtersManager.getMakeup();
+        if (mCategoryMakeupAdapter != null) {
+            mCategoryMakeupAdapter.clear();
+        }
+        mCategoryMakeupAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation makeup : makeups) {
+            if (makeup.getTextId() != 0) {
+                makeup.setName(getString(makeup.getTextId()));
+            }
+            mCategoryMakeupAdapter.add(new Action(this, makeup));
+        }
+    }
+
+    private void fillDualCamera() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getDualCamera();
+        if (mCategoryDualCamAdapter != null) {
+            mCategoryDualCamAdapter.clear();
+        }
+        mCategoryDualCamAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation representation : filtersRepresentations) {
+            if (representation.getTextId() != 0) {
+                representation.setName(getString(representation.getTextId()));
+            }
+            mCategoryDualCamAdapter.add(new Action(this, representation));
+        }
+    }
+
+    private void fillTruePortrait() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTruePortrait();
+        if (mCategoryTruePortraitAdapter != null) {
+            mCategoryTruePortraitAdapter.clear();
+        }
+        mCategoryTruePortraitAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation representation : filtersRepresentations) {
+            if (representation.getTextId() != 0) {
+                representation.setName(getString(representation.getTextId()));
+            }
+            mCategoryTruePortraitAdapter.add(new Action(this, representation));
+        }
+    }
+
+    private void fillPresetFilter() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getFilterPreset();
+        if(mChangeable) {
+            ArrayList<FilterRepresentation> mFilterPreset = new ArrayList<FilterRepresentation>();
+            ArrayList<SaveOption> ret = mFilterPresetSource.getAllUserPresets();
+            if (ret == null) return;
+            for (int id = 0; id < ret.size(); id ++) {
+                FilterPresetRepresentation representation = new FilterPresetRepresentation(
+                        ret.get(id).name, ret.get(id)._id, id + 1);
+                Uri filteredUri = Uri.parse(ret.get(id).Uri);
+                representation.setUri(filteredUri);
+                representation.setSerializationName("Custom");
+                mFilterPreset.add(representation);
+            }
+            if (tempFilterArray.size() != 0){
+                for (int id = 0; id < tempFilterArray.size(); id ++) {
+                    FilterPresetRepresentation representation = new FilterPresetRepresentation(
+                            tempFilterArray.get(id).name, tempFilterArray.get(id)._id, id + 1);
+                    Uri filteredUri = Uri.parse(tempFilterArray.get(id).Uri);
+                    representation.setUri(filteredUri);
+                    representation.setSerializationName("Custom");
+                    mFilterPreset.add(representation);
+                }
+            }
+            filtersRepresentations = mFilterPreset;
+            mChangeable = false;
+        }
+
+        if (filtersRepresentations == null) return;
+        for (FilterRepresentation representation : filtersRepresentations) {
+            mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW,true));
+        }
+    }
+
+    private void fillTrueScanner() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> trueScannerRepresentations = filtersManager.getTrueScanner();
+        if (mCategoryTrueScannerAdapter != null) {
+            mCategoryTrueScannerAdapter.clear();
+        }
+        mCategoryTrueScannerAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation representation : trueScannerRepresentations) {
+            if (representation.getTextId() != 0) {
+                representation.setName(getString(representation.getTextId()));
+            }
+            mCategoryTrueScannerAdapter.add(new Action(this, representation));
+        }
+    }
+
+    private void fillHazeBuster() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> hazeBusterRepresentations = filtersManager.getHazeBuster();
+        if (mCategoryHazeBusterAdapter != null) {
+            mCategoryHazeBusterAdapter.clear();
+        }
+        mCategoryHazeBusterAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation representation : hazeBusterRepresentations) {
+            if (representation.getTextId() != 0) {
+                representation.setName(getString(representation.getTextId()));
+            }
+            mCategoryHazeBusterAdapter.add(new Action(this, representation));
+        }
+    }
+
+    private void fillSeeStraight() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<FilterRepresentation> hazeBusterRepresentations = filtersManager.getSeeStraight();
+        if (mCategorySeeStraightAdapter != null) {
+            mCategorySeeStraightAdapter.clear();
+        }
+        mCategorySeeStraightAdapter = new CategoryAdapter(this);
+        for (FilterRepresentation representation : hazeBusterRepresentations) {
+            if (representation.getTextId() != 0) {
+                representation.setName(getString(representation.getTextId()));
+            }
+            mCategorySeeStraightAdapter.add(new Action(this, representation));
+        }
+    }
+
     private void fillTools() {
         FiltersManager filtersManager = FiltersManager.getManager();
         ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools();
@@ -475,18 +1174,29 @@
             mCategoryGeometryAdapter.clear();
         }
         mCategoryGeometryAdapter = new CategoryAdapter(this);
-        boolean found = false;
         for (FilterRepresentation representation : filtersRepresentations) {
             mCategoryGeometryAdapter.add(new Action(this, representation));
-            if (representation instanceof FilterDrawRepresentation) {
-                found = true;
-            }
         }
-        if (!found) {
-            FilterRepresentation representation = new FilterDrawRepresentation();
-            Action action = new Action(this, representation);
-            action.setIsDoubleAction(true);
-            mCategoryGeometryAdapter.add(action);
+    }
+
+    private void fillWaterMarks() {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        ArrayList<ArrayList<FilterRepresentation>> filters = new ArrayList<>();
+        filters.add(filtersManager.getWaterMarks());
+        filters.add(filtersManager.getLocations());
+        filters.add(filtersManager.getTimes());
+        filters.add(filtersManager.getWeathers());
+        filters.add(filtersManager.getEmotions());
+        filters.add(filtersManager.getFoods());
+        if (mCategoryWatermarkAdapters != null) {
+            mCategoryWatermarkAdapters.clear();
+        }
+        mCategoryWatermarkAdapters = new ArrayList<>();
+        for (int i = 0; i < filters.size(); i++) {
+            mCategoryWatermarkAdapters.add(new CategoryAdapter(this));
+            for (FilterRepresentation representation : filters.get(i)) {
+                mCategoryWatermarkAdapters.get(i).add(new Action(this, representation));
+            }
         }
     }
 
@@ -505,31 +1215,17 @@
         if (loadUri != null) {
             startLoadBitmap(loadUri);
         } else {
-            pickImage();
+            pickImage(SELECT_PICTURE);
         }
     }
 
     private void setupEditors() {
-        mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer));
+        FrameLayout editorContainer = (FrameLayout) findViewById(R.id.editorContainer);
+        mEditorPlaceHolder.setContainer(editorContainer);
         EditorManager.addEditors(mEditorPlaceHolder);
         mEditorPlaceHolder.setOldViews(mImageViews);
     }
 
-    private void fillEditors() {
-        mEditorPlaceHolder.addEditor(new EditorChanSat());
-        mEditorPlaceHolder.addEditor(new EditorGrad());
-        mEditorPlaceHolder.addEditor(new EditorDraw());
-        mEditorPlaceHolder.addEditor(new EditorColorBorder());
-        mEditorPlaceHolder.addEditor(new BasicEditor());
-        mEditorPlaceHolder.addEditor(new ImageOnlyEditor());
-        mEditorPlaceHolder.addEditor(new EditorTinyPlanet());
-        mEditorPlaceHolder.addEditor(new EditorRedEye());
-        mEditorPlaceHolder.addEditor(new EditorCrop());
-        mEditorPlaceHolder.addEditor(new EditorMirror());
-        mEditorPlaceHolder.addEditor(new EditorRotate());
-        mEditorPlaceHolder.addEditor(new EditorStraighten());
-    }
-
     private void setDefaultValues() {
         Resources res = getResources();
 
@@ -553,29 +1249,38 @@
         mShowingTinyPlanet = false;
         mLoadBitmapTask = new LoadBitmapTask();
         mLoadBitmapTask.execute(uri);
+
+        mParseDepthMapTask = new ParseDepthMapTask();
+        mParseDepthMapTask.execute(uri);
+
+        if(TruePortraitNativeEngine.getInstance().isLibLoaded()) {
+            mLoadTruePortraitTask = new LoadTruePortraitTask();
+            mLoadTruePortraitTask.execute(uri);
+        }
+    }
+
+    private void showDualCameraButton(boolean visible) {
+        if (DualCameraEffect.isSupported())
+            mReleaseDualCam = true;
+        Fragment currentPanel = getSupportFragmentManager()
+                .findFragmentByTag(MainPanel.FRAGMENT_TAG);
+        if (currentPanel instanceof MainPanel) {
+            ((MainPanel) currentPanel).showDualCameraButton(visible && mReleaseDualCam);
+        }
     }
 
     private void fillBorders() {
         FiltersManager filtersManager = FiltersManager.getManager();
         ArrayList<FilterRepresentation> borders = filtersManager.getBorders();
+        mCategoryBordersAdapter = new CategoryAdapter(this);
 
         for (int i = 0; i < borders.size(); i++) {
             FilterRepresentation filter = borders.get(i);
-            filter.setName(getString(R.string.borders));
+            filter.setName(getString(R.string.frame, i));
             if (i == 0) {
                 filter.setName(getString(R.string.none));
             }
-        }
-
-        if (mCategoryBordersAdapter != null) {
-            mCategoryBordersAdapter.clear();
-        }
-        mCategoryBordersAdapter = new CategoryAdapter(this);
-        for (FilterRepresentation representation : borders) {
-            if (representation.getTextId() != 0) {
-                representation.setName(getString(representation.getTextId()));
-            }
-            mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW));
+            mCategoryBordersAdapter.add(new Action(this, filter, Action.FULL_VIEW));
         }
     }
 
@@ -591,6 +1296,10 @@
         return mCategoryBordersAdapter;
     }
 
+    public CategoryAdapter getCategoryMakeupAdapter() {
+        return mCategoryMakeupAdapter;
+    }
+
     public CategoryAdapter getCategoryGeometryAdapter() {
         return mCategoryGeometryAdapter;
     }
@@ -599,10 +1308,54 @@
         return mCategoryFiltersAdapter;
     }
 
+    public CategoryAdapter getCategoryTrueScannerAdapter() {
+        return mCategoryTrueScannerAdapter;
+    }
+
+    public CategoryAdapter getCategoryHazeBusterAdapter() {
+        return mCategoryHazeBusterAdapter;
+    }
+
+    public CategoryAdapter getCategorySeeStraightAdapter() {
+        return mCategorySeeStraightAdapter;
+    }
+
     public CategoryAdapter getCategoryVersionsAdapter() {
         return mCategoryVersionsAdapter;
     }
 
+    public CategoryAdapter getCategoryDualCamAdapter() {
+        return mCategoryDualCamAdapter;
+    }
+
+    public CategoryAdapter getCategoryTruePortraitAdapter() {
+        return mCategoryTruePortraitAdapter;
+    }
+
+    public CategoryAdapter getCategoryWatermarkAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(0) : null;
+    }
+
+    public CategoryAdapter getCategoryLocationAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(1) : null;
+    }
+
+    public CategoryAdapter getCategoryTimeAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(2) : null;
+    }
+
+    public CategoryAdapter getCategoryWeatherAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(3) : null;
+    }
+
+    public CategoryAdapter getCategoryEmotionAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(4) : null;
+    }
+
+    public CategoryAdapter getCategoryFoodAdapter() {
+        return (mCategoryWatermarkAdapters != null) ? mCategoryWatermarkAdapters.get(5) : null;
+    }
+
     public void removeFilterRepresentation(FilterRepresentation filterRepresentation) {
         if (filterRepresentation == null) {
             return;
@@ -622,10 +1375,15 @@
             return;
         }
         if (!(filterRepresentation instanceof FilterRotateRepresentation)
-            && !(filterRepresentation instanceof FilterMirrorRepresentation)
-            && MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
+                && !(filterRepresentation instanceof FilterMirrorRepresentation)
+                && MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) {
             return;
         }
+        if (filterRepresentation.getFilterType() == FilterWatermarkRepresentation.TYPE_WATERMARK_CATEGORY) {
+            return;
+        }
+        boolean addToHistory = filterRepresentation.getFilterType()
+                != FilterWatermarkRepresentation.TYPE_WATERMARK;
         if (filterRepresentation instanceof FilterUserPresetRepresentation
                 || filterRepresentation instanceof FilterRotateRepresentation
                 || filterRepresentation instanceof FilterMirrorRepresentation) {
@@ -650,7 +1408,7 @@
                 }
             }
         }
-        MasterImage.getImage().setPreset(copy, filterRepresentation, true);
+        MasterImage.getImage().setPreset(copy, filterRepresentation, addToHistory);
         MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation);
     }
 
@@ -658,10 +1416,29 @@
         if (representation == null) {
             return;
         }
+        if (hasWaterMark && representation.getFilterType() != FilterRepresentation.TYPE_WATERMARK &&
+                representation.getFilterType() !=
+                FilterWatermarkRepresentation.TYPE_WATERMARK_CATEGORY) {
+            clearWaterMark();
+            resetHistory();
+            showWatermarkButton(false);
+        }
+
+        Fragment currentPanel =
+                getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+        if (currentPanel instanceof MainPanel && ((MainPanel) currentPanel).hasEditorPanel()) {
+            if (representation.equals(MasterImage.getImage().getCurrentFilterRepresentation())) {
+                return;
+            }
+            // cancel previous filter.
+            cancelCurrentFilter();
+            showDefaultImageView();
+            removeSeekBarPanel();
+        }
 
         if (representation instanceof FilterRotateRepresentation) {
             FilterRotateRepresentation r = (FilterRotateRepresentation) representation;
-            r.rotateCW();
+            r.rotateCCW();
         }
         if (representation instanceof FilterMirrorRepresentation) {
             FilterMirrorRepresentation r = (FilterMirrorRepresentation) representation;
@@ -676,17 +1453,107 @@
                 FilterRepresentation filterRepresentation = representation.copy();
                 MasterImage.getImage().setPreset(copy, filterRepresentation, true);
                 MasterImage.getImage().setCurrentFilterRepresentation(null);
+
+                setActionBar();
+                showActionBar(true);
+                return;
+            }
+        }
+        if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+            DisplayMetrics dm = getResources().getDisplayMetrics();
+            float[] mTmpPoint = new float[2];
+            mTmpPoint[0] = dm.widthPixels/2;
+            mTmpPoint[1] = dm.heightPixels/2;
+            Matrix m = MasterImage.getImage().getScreenToImageMatrix(true);
+            m.mapPoints(mTmpPoint);
+            if (representation instanceof FilterDualCamBasicRepresentation) {
+                ((FilterDualCamBasicRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+            }
+            if (representation instanceof FilterDualCamFusionRepresentation) {
+                ((FilterDualCamFusionRepresentation)representation).setPoint((int)mTmpPoint[0],(int)mTmpPoint[1]);
+            }
+        }
+        if (representation.getFilterType() == FilterRepresentation.TYPE_WATERMARK) {
+            if (MasterImage.getImage().getCurrentFilterRepresentation() != null
+                    && representation.getSerializationName().equals(MasterImage.getImage()
+                    .getCurrentFilterRepresentation().getSerializationName())) {
+                return;
+            }
+            showWaterMark(representation);
+        }
+        if (TrueScannerActs.SERIALIZATION_NAME.equals(representation.getSerializationName())) {
+            Bitmap b = MasterImage.getImage().getOriginalBitmapHighres();
+            int w = b.getWidth();
+            int h = b.getHeight();
+            if (w < h) {
+                w = h;
+                h = b.getWidth();
+            }
+            if (w <= TrueScannerActs.MIN_WIDTH
+                    || h <= TrueScannerActs.MIN_HEIGHT) {
+                Toast.makeText(this, getString(R.string.image_size_too_small),
+                        Toast.LENGTH_SHORT).show();
                 return;
             }
         }
         useFilterRepresentation(representation);
 
-        // show representation
-        if (mCurrentEditor != null) {
-            mCurrentEditor.detach();
+        loadEditorPanel(representation);
+    }
+
+    private void showWaterMark(FilterRepresentation representation) {
+        FilterWatermarkRepresentation watermarkRepresentation =
+                (FilterWatermarkRepresentation)representation;
+        if (mWaterMarkView != null) {
+            rlImageContainer.removeView(mWaterMarkView);
+            hasWaterMark = false;
+            watermarkRepresentation.reset();
         }
-        mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId());
-        loadEditorPanel(representation, mCurrentEditor);
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        RelativeLayout.LayoutParams params =
+                new RelativeLayout.LayoutParams(dm.widthPixels,
+                        dm.heightPixels);
+        String textHint;
+        switch (watermarkRepresentation.getMarkType()) {
+            case 0:
+                textHint = locationStr;
+                break;
+            case 2:
+                textHint = temperature;
+                break;
+            default:
+                textHint = watermarkRepresentation.getTextHint();
+                break;
+        }
+        WaterMarkView waterMarkView = watermarkRepresentation.getWaterMarkView(textHint);
+        rlImageContainer.addView(waterMarkView, params);
+        mWaterMarkView = waterMarkView;
+        mSaveWaterMark.useRepresentation(representation);
+        imgComparison.bringToFront();
+        mSaveWaterMark.getExifData(this, mSelectedImageUri);
+        mWaterMarkView.mTouchable = true;
+        hasWaterMark = true;
+    }
+
+    private void clearWaterMark() {
+        if (mWaterMarkView != null) {
+            rlImageContainer.removeView(mWaterMarkView);
+            mWaterMarkView = null;
+            hasWaterMark = false;
+        }
+    }
+
+    public void disableTouchEvent() {
+        if (mWaterMarkView == null) return;
+        mWaterMarkView.mTouchable = false;
+    }
+
+    public boolean isWaterMarked() {
+        return hasWaterMark;
+    }
+
+    public SaveWaterMark getSaveWaterMark() {
+        return mSaveWaterMark;
     }
 
     public Editor getEditor(int editorID) {
@@ -695,6 +1562,11 @@
 
     public void setCurrentPanel(int currentPanel) {
         mCurrentPanel = currentPanel;
+        if (mMasterImage == null) {
+            return;
+        }
+        HistoryManager adapter = mMasterImage.getHistory();
+        adapter.setActiveFilter(currentPanel);
     }
 
     public int getCurrentPanel() {
@@ -708,6 +1580,12 @@
         ImagePreset preset = mMasterImage.getPreset();
         mCategoryLooksAdapter.reflectImagePreset(preset);
         mCategoryBordersAdapter.reflectImagePreset(preset);
+        mCategoryFiltersAdapter.reflectImagePreset(preset);
+        if (mCategoryMakeupAdapter != null) {
+            mCategoryMakeupAdapter.reflectImagePreset(preset);
+        }
+        mCategoryDualCamAdapter.reflectImagePreset(preset);
+        mCategoryTruePortraitAdapter.reflectImagePreset(preset);
     }
 
     public View getMainStatePanelContainer(int id) {
@@ -738,22 +1616,118 @@
         mCurrentDialog = null;
     }
 
+    public void onMediaPickerStarted() {
+        toggleComparisonButtonVisibility();
+        ActionBar actionBar = getActionBar();
+        actionBar.hide();
+        if (mMediaPicker == null)
+            mMediaPicker = MediaPickerFragment.newInstance(getApplicationContext());
+        getSupportFragmentManager()
+                .beginTransaction()
+                .replace(R.id.main_panel_container, mMediaPicker)
+                .commit();
+    }
+
+    public void onMediaPickerResult(Uri selImg) {
+        mFilterPresetSource = new FilterPresetSource(this);
+        int id = nameFilter(mFilterPresetSource, tempFilterArray);
+        FilterPresetRepresentation fp= new FilterPresetRepresentation(
+                getString(R.string.filtershow_preset_title) + id, id, id);
+        fp.setSerializationName("Custom");
+        fp.setUri(selImg);
+        ImagePreset preset = new ImagePreset();
+        preset.addFilter(fp);
+        SaveOption sp= new SaveOption();
+        sp._id = id;
+        sp.name = "Custom" + id;
+        sp.Uri = selImg.toString();
+        tempFilterArray.add(sp);
+        FiltersManager.getManager().addRepresentation(fp);
+        mCategoryLooksAdapter.add(new Action(this, fp, Action.FULL_VIEW, true));
+        useFilterRepresentation(fp);
+        int pos = mCategoryLooksAdapter.getPositionOfPresentation(fp);
+        if (pos != -1)
+            backAndSetCustomFilterSelected(pos);
+    }
+
+    private void backAndSetCustomFilterSelected(int pos) {
+        showComparisonButton();
+        removeSeekBarPanel();
+        showActionBar(true);
+        loadMainPanel();
+        if(mEditorPlaceHolder != null)
+            mEditorPlaceHolder.hide();
+        if(mImageShow != null)
+            mImageShow.setVisibility(View.VISIBLE);
+        updateCategories();
+        mCategoryLooksAdapter.setSelected(pos);
+    }
+
+    public void applyCustomFilterRepresentation(
+            FilterRepresentation filterRep, FilterRepresentation oldfilterRep) {
+        ImagePreset oldPreset = MasterImage.getImage().getPreset();
+        ImagePreset copy = new ImagePreset(oldPreset);
+        if (oldfilterRep != null)
+            copy.removeFilter(oldfilterRep);
+
+        FilterRepresentation rep = copy.getRepresentation(filterRep);
+        if (rep == null) {
+            filterRep = filterRep.copy();
+            copy.addFilter(filterRep);
+        } else {
+            if (filterRep.allowsSingleInstanceOnly()) {
+                // Don't just update the filter representation. Centralize the
+                // logic in the addFilter(), such that we can keep "None" as
+                // null.
+                if (!rep.equals(filterRep)) {
+                    // Only do this if the filter isn't the same
+                    // (state panel clicks can lead us here)
+                    copy.removeFilter(rep);
+                    copy.addFilter(filterRep);
+                }
+            }
+        }
+        MasterImage.getImage().setPreset(copy, filterRep, false);
+    }
+
+    public FilterRepresentation createUserPresentaion(Uri selImg, int index) {
+        FilterPresetRepresentation fp= new FilterPresetRepresentation(
+                getString(R.string.filtershow_preset_title) + index, index, index);
+        fp.setSerializationName("Custom");
+        fp.setUri(selImg);
+        return fp;
+    }
+
+    public FilterRepresentation getCurrentPresentation() {
+        ImagePreset preset = MasterImage.getImage().getPreset();
+        return preset.getLastRepresentation();
+    }
+
     private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> {
         @Override
         protected Boolean doInBackground(Void... params) {
             MasterImage master = MasterImage.getImage();
-            Rect originalBounds = master.getOriginalBounds();
             if (master.supportsHighRes()) {
-                int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2;
-                if (highresPreviewSize > originalBounds.width()) {
-                    highresPreviewSize = originalBounds.width();
-                }
+                int highresPreviewSize = Math.min(MasterImage.MAX_BITMAP_DIM, getScreenImageSize());
+                Log.d(LOGTAG, "FilterShowActivity.LoadHighresBitmapTask.doInBackground(): after, highresPreviewSize is " + highresPreviewSize);
                 Rect bounds = new Rect();
                 Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(),
                         master.getActivity(), highresPreviewSize,
                         master.getOrientation(), bounds);
+
+                // Force the bitmap to even width and height which is required by beautification algo
+                Bitmap tempBmp = MasterImage.convertToEvenNumberWidthImage(originalHires);
+                if(tempBmp != null && originalHires != null) {
+                    if(!originalHires.isRecycled() && originalHires != tempBmp) {
+                        originalHires.recycle();
+                    }
+                    originalHires = tempBmp;
+                }
+
                 master.setOriginalBounds(bounds);
                 master.setOriginalBitmapHighres(originalHires);
+                Log.d(LOGTAG, "FilterShowActivity.LoadHighresBitmapTask.doInBackground(): originalHires.WH is (" + originalHires.getWidth()
+                        + ", " + originalHires.getHeight() +"), bounds is " + bounds.toString());
                 mBoundService.setOriginalBitmapHighres(originalHires);
                 master.warnListeners();
             }
@@ -766,26 +1740,98 @@
             if (highresBitmap != null) {
                 float highResPreviewScale = (float) highresBitmap.getWidth()
                         / (float) MasterImage.getImage().getOriginalBounds().width();
+                Log.d(LOGTAG, "FilterShowActivity.LoadHighresBitmapTask.onPostExecute(): highResPreviewScale is " + highResPreviewScale);
                 mBoundService.setHighresPreviewScaleFactor(highResPreviewScale);
             }
+
             MasterImage.getImage().warnListeners();
         }
     }
 
+    private class ParseDepthMapTask extends AsyncTask<Uri, Void, Boolean> {
+        @Override
+        protected Boolean doInBackground(Uri... params) {
+            return MasterImage.getImage().parseDepthMap(FilterShowActivity.this, params[0]);
+        }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+            showDualCameraButton(result);
+            stopLoadingIndicator();
+        }
+    }
+
     public boolean isLoadingVisible() {
-        return mLoadingVisible;
+        if (mLoadingDialog != null) {
+            return mLoadingDialog.isShowing();
+        }
+
+        return false;
     }
 
     public void startLoadingIndicator() {
-        final View loading = findViewById(R.id.loading);
-        mLoadingVisible = true;
-        loading.setVisibility(View.VISIBLE);
+        if(mLoadingDialog == null) {
+            mLoadingDialog = new ProgressDialog(this);
+            mLoadingDialog.setMessage(getString(R.string.loading_image));
+            mLoadingDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+            mLoadingDialog.setIndeterminate(true);
+            mLoadingDialog.setCancelable(true);
+            mLoadingDialog.setCanceledOnTouchOutside(false);
+            mLoadingDialog.setOnCancelListener(new OnCancelListener() {
+                @Override
+                public void onCancel(DialogInterface dialog) {
+                    done();
+                }
+            });
+        }
+
+        mLoadingDialog.show();
     }
 
     public void stopLoadingIndicator() {
-        final View loading = findViewById(R.id.loading);
-        loading.setVisibility(View.GONE);
-        mLoadingVisible = false;
+        if (mLoadingDialog != null && mLoadingDialog.isShowing()) {
+            mLoadingDialog.dismiss();
+        }
+    }
+
+    private class LoadTruePortraitTask extends AsyncTask<Uri, Void, Boolean> {
+
+        @Override
+        protected Boolean doInBackground(Uri... params) {
+            boolean result = false;
+            Bitmap src = ImageLoader.loadBitmap(FilterShowActivity.this, params[0], null);
+            if(src == null) {
+                return false;
+            }
+
+            FaceInfo[] faceInfos = null;
+            FaceDetect fDetect = new FaceDetect();
+            if (fDetect.isLibLoaded()) {
+                fDetect.initialize();
+                faceInfos = fDetect.dectectFeatures(src);
+                fDetect.uninitialize();
+            }
+
+            if(faceInfos != null && faceInfos.length > 0) {
+                Rect[] faces = new Rect[faceInfos.length];
+                for(int i=0; i<faceInfos.length; i++) {
+                    faces[i] = faceInfos[i].face;
+                }
+
+                result = TruePortraitNativeEngine.getInstance().init(FilterShowActivity.this, src, faces);
+            } else {
+                TruePortraitNativeEngine.getInstance().setFacesDetected(false);
+            }
+
+            src.recycle();
+            src = null;
+
+            return result;
+        }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+        }
     }
 
     private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> {
@@ -793,6 +1839,7 @@
 
         public LoadBitmapTask() {
             mBitmapSize = getScreenImageSize();
+            Log.d(LOGTAG, "FilterShowActivity.LoadBitmapTask(): mBitmapSize is " + mBitmapSize);
         }
 
         @Override
@@ -836,19 +1883,19 @@
                 return;
             }
 
-            if (null == CachingPipeline.getRenderScriptContext()){
-                Log.v(LOGTAG,"RenderScript context destroyed during load");
+            if (null == CachingPipeline.getRenderScriptContext()) {
+                Log.v(LOGTAG, "RenderScript context destroyed during load");
                 return;
             }
             final View imageShow = findViewById(R.id.imageShow);
             imageShow.setVisibility(View.VISIBLE);
 
-
             Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge();
             mBoundService.setOriginalBitmap(largeBitmap);
 
             float previewScale = (float) largeBitmap.getWidth()
                     / (float) MasterImage.getImage().getOriginalBounds().width();
+            Log.d(LOGTAG, "FilterShowActivity.LoadBitmapTask.onPostExecute(): previewScale is " + previewScale);
             mBoundService.setPreviewScaleFactor(previewScale);
             if (!mShowingTinyPlanet) {
                 mCategoryFiltersAdapter.removeTinyPlanet();
@@ -857,6 +1904,11 @@
             mCategoryBordersAdapter.imageLoaded();
             mCategoryGeometryAdapter.imageLoaded();
             mCategoryFiltersAdapter.imageLoaded();
+            mCategoryDualCamAdapter.imageLoaded();
+            mCategoryTruePortraitAdapter.imageLoaded();
+            if(mCategoryMakeupAdapter != null) {
+                mCategoryMakeupAdapter.imageLoaded();
+            }
             mLoadBitmapTask = null;
 
             MasterImage.getImage().warnListeners();
@@ -873,11 +1925,11 @@
 
             MasterImage.getImage().resetGeometryImages(true);
 
-            if (mAction == TINY_PLANET_ACTION) {
+            if (mAction.equals(TINY_PLANET_ACTION)) {
                 showRepresentation(mCategoryFiltersAdapter.getTinyPlanet());
             }
-            LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask();
-            highresLoad.execute();
+            mHiResBitmapTask = new LoadHighresBitmapTask();
+            mHiResBitmapTask.execute();
             MasterImage.getImage().warnListeners();
             super.onPostExecute(result);
         }
@@ -900,14 +1952,37 @@
         if (mLoadBitmapTask != null) {
             mLoadBitmapTask.cancel(false);
         }
+
+        if(mHiResBitmapTask != null) {
+            mHiResBitmapTask.cancel(false);
+        }
+
+        if(mParseDepthMapTask != null) {
+            mParseDepthMapTask.cancel(false);
+        }
+
+        if(mLoadTruePortraitTask != null) {
+            mLoadTruePortraitTask.cancel(false);
+        }
+
         mUserPresetsManager.close();
+        if (mFilterPresetSource !=null) {
+            mFilterPresetSource.close();
+        }
+
+        if (tempFilterArray != null) {
+            tempFilterArray.clear();
+        }
+        unregisterReceiver(mHandlerReceiver);
         doUnbindService();
+        if (mReleaseDualCam && DualCameraEffect.isSupported())
+            DualCameraEffect.getInstance().release();
         super.onDestroy();
     }
 
     // TODO: find a more robust way of handling image size selection
     // for high screen densities.
-    private int getScreenImageSize() {
+    public int getScreenImageSize() {
         DisplayMetrics outMetrics = new DisplayMetrics();
         getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
         return Math.max(outMetrics.heightPixels, outMetrics.widthPixels);
@@ -951,12 +2026,15 @@
             getContentResolver().insert(uri, values);
         }
         setResult(RESULT_OK, new Intent().setData(saveUri));
+        if (mReleaseDualCam && DualCameraEffect.isSupported()) {
+            DualCameraEffect.getInstance().release();
+            mReleaseDualCam = false;
+        }
         hideSavingProgress();
         finish();
     }
 
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) {
+    private boolean onShareTargetSelected() {
         // First, let's tell the SharedImageProvider that it will need to wait
         // for the image
         Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI,
@@ -985,20 +2063,29 @@
     }
 
     @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
         getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu);
-        MenuItem showState = menu.findItem(R.id.showImageStateButton);
-        if (mShowingImageStatePanel) {
-            showState.setTitle(R.string.hide_imagestate_panel);
-        } else {
-            showState.setTitle(R.string.show_imagestate_panel);
+        MenuItem item = menu.findItem(R.id.menu_share);
+        if (item != null) {
+            item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    final Intent shareIntent = getDefaultShareIntent();
+                    onShareTargetSelected();
+                    Intent intent = Intent.createChooser(shareIntent, null);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                    FilterShowActivity.this.startActivity(intent);
+                    return true;
+                }
+            });
         }
-        mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share)
-                .getActionProvider();
-        mShareActionProvider.setShareIntent(getDefaultShareIntent());
-        mShareActionProvider.setOnShareTargetSelectedListener(this);
         mMenu = menu;
         setupMenu();
+
+        if(mCurrentEditor != null) {
+            mCurrentEditor.onPrepareOptionsMenu(menu);
+        }
         return true;
     }
 
@@ -1006,36 +2093,33 @@
         if (mMenu == null || mMasterImage == null) {
             return;
         }
-        MenuItem undoItem = mMenu.findItem(R.id.undoButton);
-        MenuItem redoItem = mMenu.findItem(R.id.redoButton);
+        //MenuItem undoItem = mMenu.findItem(R.id.undoButton);
+        //MenuItem redoItem = mMenu.findItem(R.id.redoButton);
         MenuItem resetItem = mMenu.findItem(R.id.resetHistoryButton);
-        MenuItem printItem = mMenu.findItem(R.id.printButton);
-        if (!PrintHelper.systemSupportsPrint()) {
-            printItem.setVisible(false);
+        MenuItem shareItem = mMenu.findItem(R.id.menu_share);
+        //mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem);
+        if (!mMasterImage.hasModifications()) {
+            mMenu.removeItem(R.id.resetHistoryButton);
         }
-        mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem);
     }
 
     @Override
     public void onPause() {
         super.onPause();
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setOnShareTargetSelectedListener(null);
-        }
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        if (mShareActionProvider != null) {
-            mShareActionProvider.setOnShareTargetSelectedListener(this);
+        if (SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
+            MakeupEngine.getMakeupObj();
         }
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
-            case R.id.undoButton: {
+        /*case R.id.undoButton: {
                 HistoryManager adapter = mMasterImage.getHistory();
                 int position = adapter.undo();
                 mMasterImage.onHistoryItemClick(position);
@@ -1049,35 +2133,28 @@
                 mMasterImage.onHistoryItemClick(position);
                 invalidateViews();
                 return true;
-            }
-            case R.id.resetHistoryButton: {
-                resetHistory();
-                return true;
-            }
-            case R.id.showImageStateButton: {
+            }*/
+        case R.id.resetHistoryButton: {
+            clearWaterMark();
+            resetHistory();
+            return true;
+        }
+        /*case R.id.showImageStateButton: {
                 toggleImageStatePanel();
                 return true;
-            }
-            case R.id.exportFlattenButton: {
-                showExportOptionsDialog();
-                return true;
-            }
-            case android.R.id.home: {
-                saveImage();
-                return true;
-            }
-            case R.id.manageUserPresets: {
-                manageUserPresets();
-                return true;
-            }
-            case R.id.showInfoPanel: {
-                toggleInformationPanel();
-                return true;
-            }
-            case R.id.printButton: {
-                print();
-                return true;
-            }
+            }*/
+        case R.id.exportFlattenButton: {
+            showExportOptionsDialog();
+            return true;
+        }
+        case android.R.id.home: {
+            saveImage();
+            return true;
+        }
+        case R.id.manageUserPresets: {
+            manageUserPresets();
+            return true;
+        }
         }
         return false;
     }
@@ -1085,17 +2162,34 @@
     public void print() {
         Bitmap bitmap = MasterImage.getImage().getHighresImage();
         PrintHelper printer = new PrintHelper(this);
-        printer.printBitmap("ImagePrint", bitmap);
-    }
-
-    public void addNewPreset() {
-        DialogFragment dialog = new PresetManagementDialog();
-        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+        try {
+            printer.printBitmap("ImagePrint", bitmap);
+        } catch (RuntimeException e) {
+            Log.e(LOGTAG,"Print failure,",e);
+        }
     }
 
     private void manageUserPresets() {
-        DialogFragment dialog = new PresetManagementDialog();
-        dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+        if (mPresetDialog == null) {
+            mPresetDialog = new PresetManagementDialog();
+            mPresetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                @Override
+                public void onDismiss(DialogInterface dialog) {
+                    mPresetDialog = null;
+                }
+            });
+            mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+        }
+    }
+
+    public void addNewPreset() {
+        boolean skipIntro = GalleryUtils.getBooleanPref(this,
+                this.getString(R.string.pref_filtergenerator_intro_show_key), false);
+        if (!skipIntro) {
+            manageUserPresets();
+        } else {
+            onMediaPickerStarted();
+        }
     }
 
     private void showExportOptionsDialog() {
@@ -1132,19 +2226,20 @@
         if (mCategoryLooksAdapter != null) {
             fillLooks();
         }
-        if (presets.size() > 0) {
+      /*  if (presets.size() > 0) {
             mCategoryLooksAdapter.add(new Action(this, Action.SPACER));
-        }
+        } */
         mUserPresetsAdapter.clear();
+        if (presets.size() > 0) {
+            mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
+        }
         for (int i = 0; i < presets.size(); i++) {
             FilterUserPresetRepresentation representation = presets.get(i);
             mCategoryLooksAdapter.add(
                     new Action(this, representation, Action.FULL_VIEW, true));
             mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW));
         }
-        if (presets.size() > 0) {
-            mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
-        }
+
         mCategoryLooksAdapter.notifyDataSetChanged();
         mCategoryLooksAdapter.notifyDataSetInvalidated();
     }
@@ -1180,11 +2275,15 @@
         for (FilterRepresentation representation : filtersRepresentations) {
             mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW));
         }
-        if (mUserPresetsManager.getRepresentations() == null
-            || mUserPresetsManager.getRepresentations().size() == 0) {
-            mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
+        if (FilterGeneratorNativeEngine.getInstance().isLibLoaded()) {
+            if (mUserPresetsManager.getRepresentations() == null
+                    || mUserPresetsManager.getRepresentations().size() == 0) {
+                mCategoryLooksAdapter.add(new Action(this, Action.ADD_ACTION));
+            }
         }
 
+        fillPresetFilter();
+
         Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
         if (panel != null) {
             if (panel instanceof MainPanel) {
@@ -1245,18 +2344,47 @@
     }
 
     @Override
-    public void onConfigurationChanged(Configuration newConfig)
-    {
+    public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
 
         setDefaultValues();
+        if (mOrientation != newConfig.orientation) {
+            TrueScannerActs.setRotating(true);
+            mOrientation = newConfig.orientation;
+        }
+        switch (newConfig.orientation) {
+            case (Configuration.ORIENTATION_LANDSCAPE):
+                if (mPresetDialog != null) {
+                    mPresetDialog.setDismissFlag(false);
+                    mPresetDialog.dismiss();
+                    mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+                }
+                break;
+            case (Configuration.ORIENTATION_PORTRAIT):
+                if (mPresetDialog != null) {
+                    mPresetDialog.setDismissFlag(false);
+                    mPresetDialog.dismiss();
+                    mPresetDialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+                }
+                break;
+        }
+        if (isShowEditCropPanel()) {
+            mIsReloadByConfigurationChanged = true;
+            loadEditorCropPanel();
+        }
         if (mMasterImage == null) {
             return;
         }
-        loadXML();
-        fillCategories();
-        loadMainPanel();
+        //loadXML();
+        //fillCategories();
+        //loadMainPanel();
 
+        if (isWaterMarked()) {
+            DisplayMetrics dm = getResources().getDisplayMetrics();
+            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(dm.widthPixels,
+                    dm.heightPixels);
+            rlImageContainer.updateViewLayout(mWaterMarkView, params);
+        }
         if (mCurrentMenu != null) {
             mCurrentMenu.dismiss();
             mCurrentMenu = null;
@@ -1276,7 +2404,7 @@
 
         HistoryManager historyManager = new HistoryManager();
         StateAdapter imageStateAdapter = new StateAdapter(this, 0);
-        MasterImage.reset();
+        MasterImage.setMaster(null);
         mMasterImage = MasterImage.getImage();
         mMasterImage.setHistoryManager(historyManager);
         mMasterImage.setStateAdapter(imageStateAdapter);
@@ -1290,68 +2418,119 @@
     }
 
     void resetHistory() {
+        if (mMasterImage == null) {
+            return;
+        }
         HistoryManager adapter = mMasterImage.getHistory();
         adapter.reset();
         HistoryItem historyItem = adapter.getItem(0);
         ImagePreset original = null;
-        if (RESET_TO_LOADED) {
-            original = new ImagePreset(historyItem.getImagePreset());
-        } else {
-            original = new ImagePreset();
-        }
+        original = new ImagePreset();
         FilterRepresentation rep = null;
         if (historyItem != null) {
             rep = historyItem.getFilterRepresentation();
         }
         mMasterImage.setPreset(original, rep, true);
+        mMasterImage.setFusionUnderlay(null);
+        mMasterImage.resetTranslation();
+        mMasterImage.setScaleFactor(1);
+        mMasterImage.setCurrentFilterRepresentation(null);
+        ArrayList<FilterRepresentation> frList = FiltersManager.getManager().getTools();
+        for (FilterRepresentation fr : frList) {
+            if (fr instanceof FilterRotateRepresentation) {
+                ((FilterRotateRepresentation) fr).resetRotation();
+            }
+        }
+        showDefaultImageView();
+        showSaveButtonIfNeed();
         invalidateViews();
-        backToMain();
     }
 
     public void showDefaultImageView() {
-        mEditorPlaceHolder.hide();
-        mImageShow.setVisibility(View.VISIBLE);
-        MasterImage.getImage().setCurrentFilter(null);
-        MasterImage.getImage().setCurrentFilterRepresentation(null);
+        if(mEditorPlaceHolder != null)
+            mEditorPlaceHolder.hide();
+        if(mImageShow != null)
+            mImageShow.setVisibility(View.VISIBLE);
+        if(MasterImage.getImage() != null) {
+            MasterImage.getImage().setCurrentFilter(null);
+            MasterImage.getImage().setCurrentFilterRepresentation(null);
+        }
+        showWatermarkButton(true);
+    }
+
+    private void showWatermarkButton(boolean visible) {
+        Fragment currentPanel = getSupportFragmentManager()
+                .findFragmentByTag(MainPanel.FRAGMENT_TAG);
+        if (currentPanel instanceof MainPanel) {
+            ((MainPanel) currentPanel).showWatermarkButton(visible);
+        }
     }
 
     public void backToMain() {
+        removeSeekBarPanel();
+        showActionBar(true);
         Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
         if (currentPanel instanceof MainPanel) {
             return;
         }
+        mIsReloadByConfigurationChanged = false;
         loadMainPanel();
         showDefaultImageView();
+        showComparisonButton();
+    }
+
+    private void showComparisonButton() {
+        if (imgComparison != null && imgComparison.getVisibility() == View.GONE) {
+            imgComparison.setVisibility(View.VISIBLE);
+        }
     }
 
     @Override
     public void onBackPressed() {
-        Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG);
+        showComparisonButton();
+        Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(
+                MainPanel.FRAGMENT_TAG);
+
         if (currentPanel instanceof MainPanel) {
-            if (!mImageShow.hasModifications()) {
-                done();
+            if (mImageShow.hasModifications()) {
+                if (mBackAlertDialogBuilder == null) {
+                    createBackDialog();
+                }
+                mBackAlertDialogBuilder.show();
             } else {
-                AlertDialog.Builder builder = new AlertDialog.Builder(this);
-                builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit);
-                builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int id) {
-                        saveImage();
-                    }
-                });
-                builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int id) {
-                        done();
-                    }
-                });
-                builder.show();
+                done();
             }
+            setActionBar();
+            invalidateOptionsMenu();
+            if (MasterImage.getImage().getScaleFactor() < 1)
+                setScaleImage(false);
+            adjustCompareButton(false);
         } else {
+            isComingFromEditorScreen = true;
             backToMain();
         }
     }
 
+    private void createBackDialog() {
+        mBackAlertDialogBuilder = new AlertDialog.Builder(this);
+        mBackAlertDialogBuilder.setMessage(R.string.discard_message).setTitle(
+                R.string.discard_title);
+        mBackAlertDialogBuilder.setPositiveButton(mPopUpText,
+                new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int id) {
+                done();
+            }
+        });
+        mBackAlertDialogBuilder.setNegativeButton(mCancel,
+                new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int id) {
+                dialog.dismiss();
+            }
+        });
+    }
+
     public void cannotLoadImage() {
         Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show();
         finish();
@@ -1372,12 +2551,12 @@
         invalidateViews();
     }
 
-    public void pickImage() {
+    public void pickImage(int requestCode) {
         Intent intent = new Intent();
         intent.setType("image/*");
-        intent.setAction(Intent.ACTION_GET_CONTENT);
+        intent.setAction(Intent.ACTION_PICK);
         startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)),
-                SELECT_PICTURE);
+                requestCode);
     }
 
     @Override
@@ -1385,11 +2564,135 @@
         if (resultCode == RESULT_OK) {
             if (requestCode == SELECT_PICTURE) {
                 Uri selectedImageUri = data.getData();
-                startLoadBitmap(selectedImageUri);
+                if (selectedImageUri != null) {
+                    startLoadBitmap(selectedImageUri);
+                }
+            } else if (requestCode == SELECT_FUSION_UNDERLAY) {
+                Uri underlayImageUri = data.getData();
+                // find fusion representation
+                if(mCurrentEditor instanceof EditorDualCamFusion) {
+                    EditorDualCamFusion editor = (EditorDualCamFusion)mCurrentEditor;
+                    editor.setUnderlayImageUri(underlayImageUri);
+                } else if (mCurrentEditor instanceof EditorTruePortraitFusion) {
+                    if (checkExtensionValidity(this, underlayImageUri)) {
+                        Toast.makeText(getApplicationContext(), getString(R.string.not_support_gif),
+                                Toast.LENGTH_SHORT).show();
+                        pickImage(SELECT_FUSION_UNDERLAY);
+                    } else {
+                        EditorTruePortraitFusion editor = (EditorTruePortraitFusion)mCurrentEditor;
+                        editor.setUnderlayImageUri(underlayImageUri);
+                    }
+                }
             }
         }
     }
 
+    /**
+     * check whether the extension of the given uri is supported to be underlay
+     * @param context context for get ContentResolver
+     * @param uri uri need to check
+     * @return validity of uri's extension, true means unsupported, false means supported
+     */
+    private boolean checkExtensionValidity(final Context context, final Uri uri) {
+        if (uri == null) {
+            return false;
+        }
+        // get file path from uri
+        String filePath = null;
+        final String scheme = uri.getScheme();
+        if (scheme == null || ContentResolver.SCHEME_FILE.equals(scheme)) {
+            filePath = uri.getPath();
+        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
+            Cursor cursor = context.getContentResolver().query(
+                    uri, new String[] {MediaStore.Images.ImageColumns.DATA}, null, null, null);
+            if (null != cursor) {
+                if (cursor.moveToFirst()) {
+                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
+                    if (index > -1) {
+                        filePath = cursor.getString(index);
+                    }
+                }
+                cursor.close();
+            }
+        }
+
+        //get extension from filepath
+        String extension = MimeTypeMap.getFileExtensionFromUrl(filePath);
+
+        //check validity of extension
+        boolean notSupported = false;
+        //if have new unsupported extension, add it below
+        notSupported |= (extension.equals("gif") || extension.equals("GIF"));
+        return notSupported;
+    }
+
+    private int nameFilter(FilterPresetSource source,
+                                            ArrayList <SaveOption> tempFilterArray) {
+        String s,s1,s2;
+        ArrayList<SaveOption> sp = source.getAllUserPresets();
+        ArrayList<Integer> temp = new ArrayList<Integer>();
+        if (sp != null) {
+            for (int i = 0; i < sp.size(); i++) {
+                s = sp.get(i).name;
+                if (s.length() > "Custom".length()) {
+                    s1 = s.substring(0, 6);
+                    if (s1.equals("Custom")) {
+                        s2 = s.substring(6);
+                        int tem;
+                        try {
+                            tem = Integer.parseInt(s2);
+                        } catch (NumberFormatException e) {
+                            continue;
+                        }
+                        temp.add(tem);
+                    }
+                }
+            }
+        }
+
+        if (tempFilterArray.size() != 0 ){
+            for (int i = 0; i < tempFilterArray.size(); i++) {
+                s = tempFilterArray.get(i).name;
+                if (s.length() > "Custom".length()) {
+                    s1 = s.substring(0, 6);
+                    if (s1.equals("Custom")) {
+                        s2 = s.substring(6);
+                        int tem;
+                        try {
+                            tem = Integer.parseInt(s2);
+                        } catch (NumberFormatException e) {
+                            continue;
+                        }
+                        temp.add(tem);
+                    }
+                }
+            }
+
+        }
+
+        if (temp != null) {
+            Collections.sort(temp);
+            for (int i = 1; i <= temp.size(); i++){
+                if (temp.get(i-1)!= i){
+                    return i;
+                }
+            }
+        }
+        return temp.size()+1;
+    }
+
+
+    public static boolean completeSaveFilters (FilterPresetSource mFilterPresetSource,
+                                               ArrayList<SaveOption> tempFilterArray) {
+
+        for (int i = 0; i < tempFilterArray.size(); i++){
+            String name = tempFilterArray.get(i).name;
+            String filteredUri = tempFilterArray.get(i).Uri;
+            if (mFilterPresetSource.insertPreset(name,filteredUri) == false) return false;
+        }
+        tempFilterArray.clear();
+        return true;
+    }
 
     public void saveImage() {
         if (mImageShow.hasModifications()) {
@@ -1398,7 +2701,15 @@
             int bucketId = GalleryUtils.getBucketId(saveDir.getPath());
             String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null);
             showSavingProgress(albumName);
-            mImageShow.saveImage(this, null);
+            if (mWaterMarkView == null) {
+                mImageShow.saveImage(this, null);
+            } else {
+                mSaveWaterMark.saveImage(this, mMasterImage.getHighresImage(),
+                        mSelectedImageUri, handler);
+            }
+            if (tempFilterArray.size() != 0) {
+                completeSaveFilters(mFilterPresetSource, tempFilterArray);
+            }
         } else {
             done();
         }
@@ -1474,7 +2785,7 @@
                 if (mHandledSwipeViewLastDelta > distance) {
                     ((SwipableView) mHandledSwipeView).delete();
                 }
-            }
+           }
             return true;
         }
         return super.dispatchTouchEvent(ev);
@@ -1491,27 +2802,49 @@
     }
 
     public void startTouchAnimation(View target, float x, float y) {
-        final CategorySelected hint =
-                (CategorySelected) findViewById(R.id.categorySelectedIndicator);
         int location[] = new int[2];
         target.getLocationOnScreen(location);
         mHintTouchPoint.x = (int) (location[0] + x);
         mHintTouchPoint.y = (int) (location[1] + y);
-        int locationHint[] = new int[2];
-        ((View)hint.getParent()).getLocationOnScreen(locationHint);
-        int dx = (int) (x - (hint.getWidth())/2);
-        int dy = (int) (y - (hint.getHeight())/2);
-        hint.setTranslationX(location[0] - locationHint[0] + dx);
-        hint.setTranslationY(location[1] - locationHint[1] + dy);
-        hint.setVisibility(View.VISIBLE);
-        hint.animate().scaleX(2).scaleY(2).alpha(0).withEndAction(new Runnable() {
-            @Override
-            public void run() {
-                hint.setVisibility(View.INVISIBLE);
-                hint.setScaleX(1);
-                hint.setScaleY(1);
-                hint.setAlpha(1);
-            }
-        });
+    }
+
+    public void setScaleImage(boolean isScaled) {
+        mImageShow.scaleImage(isScaled, getBaseContext());
+    }
+
+    public void saveEditorCropState(int select) {
+        mEditrCropButtonSelect = select;
+    }
+
+    public boolean isReloadByConfigurationChanged() {
+        return mIsReloadByConfigurationChanged;
+    }
+
+    public boolean isShowEditCropPanel() {
+        if (mCurrentEditor == null) {
+            return false;
+        }
+        Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(
+                MainPanel.FRAGMENT_TAG);
+        if (currentPanel instanceof MainPanel) {
+            return false;
+        }
+        return mCurrentEditor.getID() == EditorCrop.ID;
+    }
+
+    public int getEditorCropButtonSelect() {
+        return mEditrCropButtonSelect;
+    }
+
+    @Override
+    protected void onGetPermissionsFailure() {
+        finish();
+    }
+
+    @Override
+    protected void onGetPermissionsSuccess() {
+        if (canUpdataUI) {
+            updateUIAfterServiceStarted();
+        }
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
index cd63d30..82129c2 100644
--- a/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
+++ b/src/com/android/gallery3d/filtershow/cache/BitmapCache.java
@@ -16,16 +16,18 @@
 
 package com.android.gallery3d.filtershow.cache;
 
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.util.Log;
-import com.android.gallery3d.filtershow.pipeline.Buffer;
-import com.android.gallery3d.filtershow.pipeline.CacheProcessing;
-
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.util.Log;
+
+import com.android.gallery3d.filtershow.pipeline.Buffer;
+import com.android.gallery3d.filtershow.pipeline.CacheProcessing;
+
 public class BitmapCache {
     private static final String LOGTAG = "BitmapCache";
     private HashMap<Long, ArrayList<WeakReference<Bitmap>>>
@@ -205,6 +207,7 @@
 
     public synchronized Bitmap getBitmapCopy(Bitmap source, int type) {
         Bitmap bitmap = getBitmap(source.getWidth(), source.getHeight(), type);
+        bitmap.eraseColor(Color.TRANSPARENT);
         Canvas canvas = new Canvas(bitmap);
         canvas.drawBitmap(source, 0, 0, null);
         return bitmap;
@@ -213,4 +216,8 @@
     private Long calcKey(long w, long h) {
         return (w << 32) | h;
     }
+
+    public synchronized void clear() {
+        mBitmapCache.clear();
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 52c296c..f70a8fe 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -17,6 +17,7 @@
 package com.android.gallery3d.filtershow.cache;
 
 import android.content.ContentResolver;
+import android.content.ContentUris;
 import android.content.Context;
 import android.content.res.Resources;
 import android.database.Cursor;
@@ -29,6 +30,9 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
 import android.provider.MediaStore;
 import android.util.Log;
 import android.webkit.MimeTypeMap;
@@ -82,14 +86,97 @@
     }
 
     public static String getLocalPathFromUri(Context context, Uri uri) {
-        Cursor cursor = context.getContentResolver().query(uri,
-                new String[]{MediaStore.Images.Media.DATA}, null, null, null);
-        if (cursor == null) {
-            return null;
+
+        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
+        // DocumentProvider
+        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+            // ExternalStorageProvider
+            if (isExternalStorageDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    return Environment.getExternalStorageDirectory() + "/" + split[1];
+                }
+            }
+            // DownloadsProvider
+            else if (isDownloadsDocument(uri)) {
+
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(
+                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+                return getDataColumn(context, contentUri, null, null);
+            }
+            // MediaProvider
+            else if (isMediaDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[] { split[1] };
+
+                return getDataColumn(context, contentUri, selection, selectionArgs);
+            }
         }
-        int index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
-        cursor.moveToFirst();
-        return cursor.getString(index);
+        return getDataColumn(context, uri, null, null);
+    }
+
+    public static String getDataColumn(Context context, Uri uri, String selection,
+                                       String[] selectionArgs) {
+
+        Cursor cursor = null;
+        final String column = "_data";
+        final String[] projection = { column };
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+                final int index = cursor.getColumnIndexOrThrow(column);
+                return cursor.getString(index);
+            }
+        } finally {
+            if (cursor != null)
+                cursor.close();
+        }
+        return null;
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is ExternalStorageProvider.
+     */
+    public static boolean isExternalStorageDocument(Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is DownloadsProvider.
+     */
+    public static boolean isDownloadsDocument(Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is MediaProvider.
+     */
+    public static boolean isMediaDocument(Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
     }
 
     /**
@@ -147,6 +234,8 @@
             return parseExif(exif);
         } catch (IOException e) {
             Log.w(LOGTAG, "Failed to read EXIF orientation", e);
+        } catch (NullPointerException e) {
+            Log.w(LOGTAG, "Invalid EXIF data", e);
         } finally {
             try {
                 if (is != null) {
@@ -576,6 +665,8 @@
                 return taglist;
             } catch (IOException e) {
                 Log.w(LOGTAG, "Failed to read EXIF tags", e);
+            } catch (NullPointerException e) {
+                Log.e(LOGTAG, "Failed to read EXIF tags", e);
             }
         }
         return null;
diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java
index b3a4148..67a34ce 100644
--- a/src/com/android/gallery3d/filtershow/category/Action.java
+++ b/src/com/android/gallery3d/filtershow/category/Action.java
@@ -20,16 +20,23 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.util.Log;
 import android.widget.ArrayAdapter;
 import android.widget.ListAdapter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
 import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
 import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
@@ -37,6 +44,7 @@
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.glrenderer.Texture;
 
 public class Action implements RenderingRequestCaller {
 
@@ -57,6 +65,7 @@
     private boolean mCanBeRemoved = false;
     private int mTextSize = 32;
     private boolean mIsDoubleAction = false;
+    private boolean mIsClickAction = false;
 
     public Action(FilterShowActivity context, FilterRepresentation representation, int type,
                   boolean canBeRemoved) {
@@ -121,6 +130,17 @@
         if (getType() == Action.ADD_ACTION) {
             return;
         }
+
+        if (mRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK ||
+                mRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+            mImageFrame = imageFrame;
+            int w = mImageFrame.width();
+            int h = mImageFrame.height();
+            mImage = MasterImage.getImage().getBitmapCache().getBitmap(w, h, BitmapCache.ICON);
+            drawOverlay();
+            return;
+        }
+
         Bitmap temp = MasterImage.getImage().getTemporaryThumbnailBitmap();
         if (temp != null) {
             mImage = temp;
@@ -165,22 +185,36 @@
 
         float dx = (destination.getWidth() - source.getWidth() * scaleFactor) / 2.0f;
         float dy = (destination.getHeight() - source.getHeight() * scaleFactor) / 2.0f;
-        if (mImageFrame.height() > mImageFrame.width()) {
-            // if portrait
-            dy -= mTextSize;
-        }
         m.setScale(scaleFactor, scaleFactor);
         m.postTranslate(dx, dy);
         Canvas canvas = new Canvas(destination);
         canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG));
     }
 
-    @Override
-    public void available(RenderingRequest request) {
-        clearBitmap();
-        mImage = request.getBitmap();
-        if (mImage == null) {
-            mImageFrame = null;
+    protected void drawOverlay() {
+        if (mRepresentation.isSvgOverlay()) {
+            mImage.eraseColor(0x00FFFFFF);
+            Canvas canvas = new Canvas(mImage);
+            canvas.drawARGB(0,255,255,255);
+            Drawable overlayDrawable = mContext.getResources().
+                    getDrawable(mRepresentation.getOverlayId(), null);
+            if (null != mRepresentation.getCurrentTheme() && overlayDrawable.canApplyTheme()) {
+                overlayDrawable.applyTheme(mRepresentation.getCurrentTheme());
+            }
+            if(mIsClickAction) {
+                overlayDrawable.setColorFilter(mContext.getResources()
+                        .getColor(R.color.watermark_highlight_color), PorterDuff.Mode.MULTIPLY);
+            } else {
+                overlayDrawable.clearColorFilter();
+            }
+            int with = mImageFrame.width()/9;
+            int height = mImageFrame.height()/8;
+            if (!TextUtils.isEmpty(getName())) {
+                overlayDrawable.setBounds(with,16,with*8,height*6);
+            } else {
+                overlayDrawable.setBounds(with,52,with*8,height*7);
+            }
+            overlayDrawable.draw(canvas);
             return;
         }
         if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) {
@@ -199,6 +233,17 @@
                 drawCenteredImage(mOverlayBitmap, mImage, false);
             }
         }
+    }
+
+    @Override
+    public void available(RenderingRequest request) {
+        clearBitmap();
+        mImage = request.getBitmap();
+        if (mImage == null) {
+            mImageFrame = null;
+            return;
+        }
+        drawOverlay();
         if (mAdapter != null) {
             mAdapter.notifyDataSetChanged();
         }
@@ -220,6 +265,10 @@
         mOverlayBitmap = overlayBitmap;
     }
 
+    public void setClickAction() { mIsClickAction = true; }
+
+    public void clearClickAction() { mIsClickAction = false; }
+
     public void clearBitmap() {
         if (mImage != null
                 && mImage != MasterImage.getImage().getTemporaryThumbnailBitmap()) {
diff --git a/src/com/android/gallery3d/filtershow/category/BasicGeometryPanel.java b/src/com/android/gallery3d/filtershow/category/BasicGeometryPanel.java
new file mode 100644
index 0000000..d27954b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/BasicGeometryPanel.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+
+import android.content.res.Configuration;
+import android.os.Bundle;
+import androidx.fragment.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import org.codeaurora.gallery.R;
+
+public class BasicGeometryPanel extends Fragment {
+    protected View mMainView;
+    protected ImageButton mExitButton;
+    protected ImageButton mApplyButton;
+    protected View mBottomPanel;
+    protected TextView mEditorName;
+
+    protected ImageButton[] mButtons;
+    protected TextView[] mTextViews;
+    protected View[] mPanels;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
+        if (isLandscape() && activity.isShowEditCropPanel()) {
+            mMainView = inflater.inflate(R.layout.filtershow_editor_crop_landscape,
+                    container, false);
+        } else {
+            mMainView = inflater.inflate(R.layout.filtershow_category_geometry_panel,
+                    container, false);
+            mEditorName = (TextView) mMainView.findViewById(R.id.editor_name);
+        }
+
+        initButtons();
+        initTexts();
+        initPanels();
+
+        mBottomPanel = mMainView.findViewById(R.id.bottom_panel);
+
+        mExitButton = (ImageButton) mMainView.findViewById(R.id.cancel);
+        mApplyButton = (ImageButton) mMainView.findViewById(R.id.done);
+        return mMainView;
+    }
+
+    protected void initButtons() {
+        mButtons = new ImageButton[] {
+                (ImageButton) mMainView.findViewById(R.id.leftButton),
+                (ImageButton) mMainView.findViewById(R.id.centerButton),
+                (ImageButton) mMainView.findViewById(R.id.rightButton)
+        };
+    }
+
+    protected void initTexts() {
+        mTextViews = new TextView[] {
+                (TextView) mMainView.findViewById(R.id.leftText),
+                (TextView) mMainView.findViewById(R.id.centerText),
+                (TextView) mMainView.findViewById(R.id.rightText)
+        };
+    }
+
+    protected void initPanels() {
+        mPanels = new View[] {
+                mMainView.findViewById(R.id.leftPanel),
+                mMainView.findViewById(R.id.centerPanel),
+                mMainView.findViewById(R.id.rightPanel)
+        };
+    }
+
+    protected boolean isLandscape() {
+        Configuration mConfiguration = this.getResources().getConfiguration();
+        return mConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE ?
+                true : false;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/BottomPanel.java b/src/com/android/gallery3d/filtershow/category/BottomPanel.java
new file mode 100644
index 0000000..5886cc9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/BottomPanel.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+import android.os.Bundle;
+import androidx.fragment.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BottomPanel extends Fragment {
+    public static final String FRAGMENT_TAG = "BottomPanel";
+
+    private BottomPanelDelegate mPanelDelegate;
+    private View mBottomView;
+
+    interface BottomPanelDelegate {
+        View getBottomPanelView(LayoutInflater inflater);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        if (mBottomView == null && mPanelDelegate != null) {
+            mBottomView = mPanelDelegate.getBottomPanelView(inflater);
+        }
+        return mBottomView;
+    }
+
+    public void setBottomPanelDelegate(BottomPanelDelegate panelDelegate) {
+        mPanelDelegate = panelDelegate;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
index 09f02dd..22ffc04 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java
@@ -22,8 +22,9 @@
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
@@ -31,6 +32,7 @@
 public class CategoryAdapter extends ArrayAdapter<Action> {
 
     private static final String LOGTAG = "CategoryAdapter";
+    private static final int UNKNOWN_INDEX = -1;
     private int mItemHeight;
     private View mContainer;
     private int mItemWidth = ListView.LayoutParams.MATCH_PARENT;
@@ -79,9 +81,31 @@
             mSelectedPosition = 0;
             mAddButtonText = getContext().getString(R.string.filtershow_add_button_looks);
         }
+        //        if (category == MainPanel.MAKEUP) {
+        //            mSelectedPosition = 0;
+        //        }
         if (category == MainPanel.BORDERS) {
             mSelectedPosition = 0;
         }
+        if (category == MainPanel.DUALCAM) {
+            mSelectedPosition = 0;
+        }
+        if (category == MainPanel.TRUEPORTRAIT) {
+            mSelectedPosition = 0;
+        }
+
+        if (category == MainPanel.TRUESCANNER) {
+            mSelectedPosition = 0;
+        }
+
+        if (category == MainPanel.HAZEBUSTER) {
+            mSelectedPosition = 0;
+        }
+
+        if (category == MainPanel.SEESTRAIGHT) {
+            mSelectedPosition = 0;
+        }
+
         if (category == MainPanel.VERSIONS) {
             mAddButtonText = getContext().getString(R.string.filtershow_add_button_versions);
         }
@@ -117,11 +141,31 @@
     }
 
     public void setSelected(View v) {
+        setSelected((Integer) v.getTag());
+    }
+
+    public int getPositionOfPresentation(FilterRepresentation rep) {
+        int pos = -1;
+        for (int i = 0; i < getCount(); i++) {
+            FilterRepresentation itemRep = getItem(i).getRepresentation();
+            if (itemRep == null) {
+                continue;
+            }
+            if (rep.getName().equalsIgnoreCase(
+                    itemRep.getName())) {
+                pos = i;
+                break;
+            }
+        }
+        return pos;
+    }
+
+    public void setSelected(int pos) {
         int old = mSelectedPosition;
-        mSelectedPosition = (Integer) v.getTag();
         if (old != -1) {
             invalidateView(old);
         }
+        mSelectedPosition = pos;
         invalidateView(mSelectedPosition);
     }
 
@@ -129,6 +173,10 @@
         return (Integer) v.getTag() == mSelectedPosition;
     }
 
+    public int getCurrentSelection() {
+        return mSelectedPosition;
+    }
+
     private void invalidateView(int position) {
         View child = null;
         if (mContainer instanceof ListView) {
@@ -184,7 +232,11 @@
         super.remove(action);
         FilterShowActivity activity = (FilterShowActivity) getContext();
         if (mCategory == MainPanel.LOOKS) {
-            activity.removeLook(action);
+            if ((FilterPresetRepresentation)action.getRepresentation() != null ){
+                activity.removePreset(action);
+            } else {
+                activity.removeLook(action);
+            }
         } else if (mCategory == MainPanel.VERSIONS) {
             activity.removeVersion(action);
         }
@@ -204,12 +256,28 @@
             int pos = preset.getPositionForType(FilterRepresentation.TYPE_FX);
             if (pos != -1) {
                 rep = preset.getFilterRepresentation(pos);
+            } else {
+                pos = preset.getPositionForType(FilterRepresentation.TYPE_PRESETFILTER);
+                if (pos != -1)
+                    rep = preset.getFilterRepresentation(pos);
             }
         } else if (mCategory == MainPanel.BORDERS) {
             int pos = preset.getPositionForType(FilterRepresentation.TYPE_BORDER);
             if (pos != -1) {
                 rep = preset.getFilterRepresentation(pos);
             }
+        } else if (mCategory == MainPanel.DUALCAM) {
+            int pos = preset.getPositionForType(FilterRepresentation.TYPE_DUALCAM);
+            if (pos != -1) {
+                rep = preset.getFilterRepresentation(pos);
+            }
+        } else if (mCategory == MainPanel.TRUEPORTRAIT) {
+            int pos = preset.getPositionForType(FilterRepresentation.TYPE_TRUEPORTRAIT);
+            if (pos != -1) {
+                rep = preset.getFilterRepresentation(pos);
+            }
+        } else if (mCategory == MainPanel.FILTERS || mCategory == MainPanel.MAKEUP) {
+            selected = UNKNOWN_INDEX;
         }
         if (rep != null) {
             for (int i = 0; i < getCount(); i++) {
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
index c7aadfa..f8669dc 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java
@@ -27,17 +27,17 @@
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.TextView;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
-
+import android.util.Log;
 public class CategoryPanel extends Fragment implements View.OnClickListener {
 
     public static final String FRAGMENT_TAG = "CategoryPanel";
     private static final String PARAMETER_TAG = "currentPanel";
 
-    private int mCurrentAdapter = MainPanel.LOOKS;
-    private CategoryAdapter mAdapter;
-    private IconView mAddButton;
+    protected int mCurrentAdapter = MainPanel.LOOKS;
+    protected CategoryAdapter mAdapter;
+    protected IconView mAddButton;
 
     public void setAdapter(int value) {
         mCurrentAdapter = value;
@@ -82,6 +82,43 @@
                 }
                 break;
             }
+            case MainPanel.DUALCAM: {
+                mAdapter = activity.getCategoryDualCamAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.DUALCAM);
+                }
+                activity.updateCategories();
+                break;
+            }
+            case MainPanel.TRUEPORTRAIT: {
+                mAdapter = activity.getCategoryTruePortraitAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.TRUEPORTRAIT);
+                }
+                activity.updateCategories();
+                break;
+            }
+            case MainPanel.TRUESCANNER: {
+                mAdapter = activity.getCategoryTrueScannerAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.TRUESCANNER);
+                }
+                break;
+            }
+            case MainPanel.HAZEBUSTER: {
+                mAdapter = activity.getCategoryHazeBusterAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.HAZEBUSTER);
+                }
+                break;
+            }
+            case MainPanel.SEESTRAIGHT: {
+                mAdapter = activity.getCategorySeeStraightAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.SEESTRAIGHT);
+                }
+                break;
+            }
             case MainPanel.VERSIONS: {
                 mAdapter = activity.getCategoryVersionsAdapter();
                 if (mAdapter != null) {
@@ -89,6 +126,20 @@
                 }
                 break;
             }
+           case MainPanel.MAKEUP: {
+                mAdapter = activity.getCategoryMakeupAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.MAKEUP);
+                }
+                break;
+            }
+           case MainPanel.WATERMARK: {
+               mAdapter = activity.getCategoryWatermarkAdapter();
+               if (mAdapter != null) {
+                   mAdapter.initializeSelection(MainPanel.WATERMARK);
+               }
+               break;
+           }
         }
         updateAddButtonVisibility();
     }
@@ -148,7 +199,7 @@
             return;
         }
         FilterShowActivity activity = (FilterShowActivity) getActivity();
-        if (activity.isShowingImageStatePanel() && mAdapter.showAddButton()) {
+        if (activity.isShowingImageStatePanel() && mAdapter != null && mAdapter.showAddButton()) {
             mAddButton.setVisibility(View.VISIBLE);
             if (mAdapter != null) {
                 mAddButton.setText(mAdapter.getAddButtonText());
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java b/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java
new file mode 100644
index 0000000..26875f3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/CategoryPanelLevelTwo.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+
+import java.util.ArrayList;
+
+public class CategoryPanelLevelTwo extends CategoryPanel {
+
+    private View mBottomPanel;
+    private ImageButton mExitButton;
+    private ImageButton mApplyButton;
+    private TextView mEditName;
+    private ArrayList<FilterRepresentation> mFiltersRepresentations;
+    private static final String DEFAULT_NAME = "LEVEL_TWO";
+
+    public CategoryPanelLevelTwo(int adapter) {
+        setAdapter(adapter);
+    }
+
+    public CategoryPanelLevelTwo() {}
+
+    @Override
+    public void loadAdapter(int adapter) {
+        super.loadAdapter(adapter);
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
+        switch (adapter) {
+            case FilterWatermarkRepresentation.LOCATION: {
+                mAdapter = activity.getCategoryLocationAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.WATERMARK);
+                }
+                break;
+            }
+            case FilterWatermarkRepresentation.TIME: {
+                mAdapter = activity.getCategoryTimeAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.WATERMARK);
+                }
+                break;
+            }
+            case FilterWatermarkRepresentation.WEATHER: {
+                mAdapter = activity.getCategoryWeatherAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.WATERMARK);
+                }
+                break;
+            }
+            case FilterWatermarkRepresentation.EMOTIONS: {
+                mAdapter = activity.getCategoryEmotionAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.WATERMARK);
+                }
+                break;
+            }
+            case FilterWatermarkRepresentation.FOOD: {
+                mAdapter = activity.getCategoryFoodAdapter();
+                if (mAdapter != null) {
+                    mAdapter.initializeSelection(MainPanel.WATERMARK);
+                }
+                break;
+            }
+        }
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        LinearLayout main = (LinearLayout) inflater.inflate(
+                R.layout.filtershow_category_panel_two, container,
+                false);
+        FiltersManager filtersManager = FiltersManager.getManager();
+        mFiltersRepresentations = filtersManager.getWaterMarks();
+        mBottomPanel = main.findViewById(R.id.bottom_panel);
+        mExitButton = (ImageButton) main.findViewById(R.id.cancel);
+        mApplyButton = (ImageButton) main.findViewById(R.id.done);
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        mApplyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                //Todo xukd add watermark to bufferimage
+                activity.disableTouchEvent();
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+        mExitButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                activity.cancelCurrentFilter();
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+        mEditName = (TextView) main.findViewById(R.id.editor_name);
+        int adapterId = mCurrentAdapter % FilterWatermarkRepresentation.LOCATION;
+        if (adapterId >= 0 && adapterId < mFiltersRepresentations.size()) {
+            mEditName.setText(mFiltersRepresentations.get(adapterId).getTextId());
+        } else {
+            mEditName.setText(DEFAULT_NAME);
+        }
+        View panelView = main.findViewById(R.id.listItems);
+        if (panelView instanceof CategoryTrack) {
+            CategoryTrack panel = (CategoryTrack) panelView;
+            if (mAdapter != null) {
+                mAdapter.setOrientation(CategoryView.HORIZONTAL);
+                panel.setAdapter(mAdapter);
+                mAdapter.setContainer(panel);
+            }
+        }
+        mAddButton = (IconView) main.findViewById(R.id.addButton);
+        if (mAddButton != null) {
+            mAddButton.setOnClickListener(this);
+            updateAddButtonVisibility();
+        }
+        return main;
+    }
+
+    private void setEditName() {
+
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/CategorySelected.java b/src/com/android/gallery3d/filtershow/category/CategorySelected.java
index 42058c0..92848c1 100644
--- a/src/com/android/gallery3d/filtershow/category/CategorySelected.java
+++ b/src/com/android/gallery3d/filtershow/category/CategorySelected.java
@@ -7,7 +7,7 @@
 import android.util.AttributeSet;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class CategorySelected extends View {
     private Paint mPaint = new Paint();
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java b/src/com/android/gallery3d/filtershow/category/CategoryTrack.java
index 1371fe8..a906df5 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryTrack.java
@@ -25,7 +25,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class CategoryTrack extends LinearLayout {
 
diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java
index 1570517..d9788cf 100644
--- a/src/com/android/gallery3d/filtershow/category/CategoryView.java
+++ b/src/com/android/gallery3d/filtershow/category/CategoryView.java
@@ -24,14 +24,25 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.ContextThemeWrapper;
 import android.view.MotionEvent;
 import android.view.View;
-import com.android.gallery3d.R;
+import android.view.ActionMode;
+import android.widget.PopupMenu;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.Log;
 import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterWatermarkRepresentation;
 import com.android.gallery3d.filtershow.ui.SelectionRenderer;
 
+import java.util.ArrayList;
+
 public class CategoryView extends IconView
-        implements View.OnClickListener, SwipableView{
+        implements View.OnClickListener, SwipableView,View.OnLongClickListener,PopupMenu.OnMenuItemClickListener{
 
     private static final String LOGTAG = "CategoryView";
     public static final int VERTICAL = 0;
@@ -43,6 +54,7 @@
     private int mSelectionStroke;
     private Paint mBorderPaint;
     private int mBorderStroke;
+    private Context mContext;
     private float mStartTouchX = 0;
     private float mStartTouchY = 0;
     private float mDeleteSlope = 20;
@@ -54,7 +66,9 @@
 
     public CategoryView(Context context) {
         super(context);
+        mContext = context;
         setOnClickListener(this);
+        setOnLongClickListener(this);
         Resources res = getResources();
         mSelectionStroke = res.getDimensionPixelSize(R.dimen.thumbnail_margin);
         mSelectPaint = new Paint();
@@ -64,7 +78,7 @@
 
         mSelectPaint.setColor(mSelectionColor);
         mBorderPaint = new Paint(mSelectPaint);
-        mBorderPaint.setColor(Color.BLACK);
+        mBorderPaint.setColor(res.getColor(R.color.filtershow_info_test));
         mBorderStroke = mSelectionStroke / 3;
     }
 
@@ -120,11 +134,21 @@
             }
         }
         super.onDraw(canvas);
-        if (mAdapter.isSelected(this)) {
-            SelectionRenderer.drawSelection(canvas, 0, 0,
-                    getWidth(), getHeight(),
-                    mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
+        if (mAction.getRepresentation() == null) {
+            return;
         }
+        if (mAdapter.isSelected(this)) {
+            mAction.setClickAction();
+            if (mAction.getRepresentation().getFilterType() != FilterRepresentation.TYPE_WATERMARK_CATEGORY
+                    && mAction.getRepresentation().getFilterType() != FilterRepresentation.TYPE_WATERMARK) {
+                SelectionRenderer.drawSelection(canvas, getMargin() / 2, getMargin(),
+                        getWidth() - getMargin() / 2, getHeight() - getMargin(),
+                        mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint);
+            }
+        } else {
+            mAction.clearClickAction();
+        }
+        mAction.drawOverlay();
     }
 
     public void setAction(Action action, CategoryAdapter adapter) {
@@ -134,10 +158,11 @@
         mCanBeRemoved = action.canBeRemoved();
         setUseOnlyDrawable(false);
         if (mAction.getType() == Action.ADD_ACTION) {
-            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.filtershow_add);
+            Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
+                    R.drawable.filtershow_add_new);
             setBitmap(bitmap);
-            setUseOnlyDrawable(true);
-            setText(getResources().getString(R.string.filtershow_add_button_looks));
+         //   setUseOnlyDrawable(true);
+         //   setText(getResources().getString(R.string.filtershow_add_button_looks));
         } else {
             setBitmap(mAction.getImage());
         }
@@ -171,12 +196,13 @@
         if (event.getActionMasked() == MotionEvent.ACTION_UP) {
             activity.startTouchAnimation(this, event.getX(), event.getY());
         }
-        if (!canBeRemoved()) {
+        if (!canBeRemoved() || checkPreset()) {
             return ret;
         }
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
             mStartTouchY = event.getY();
             mStartTouchX = event.getX();
+
         }
         if (event.getActionMasked() == MotionEvent.ACTION_UP) {
             setTranslationX(0);
@@ -187,7 +213,7 @@
             if (getOrientation() == CategoryView.VERTICAL) {
                 delta = event.getX() - mStartTouchX;
             }
-            if (Math.abs(delta) > mDeleteSlope) {
+           if (Math.abs(delta) > mDeleteSlope) {
                 activity.setHandlesSwipeForView(this, mStartTouchX, mStartTouchY);
             }
         }
@@ -195,7 +221,70 @@
     }
 
     @Override
+    public boolean onLongClick(View view){
+        if (canBeRemoved()){
+            mAdapter.setSelected(this);
+            PopupMenu popup = new PopupMenu((FilterShowActivity)getContext(),view);
+            popup.getMenuInflater().inflate(R.menu.filtershow_menu_edit,popup.getMenu());
+            popup.setOnMenuItemClickListener(this);
+            popup.show();
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onMenuItemClick (MenuItem item) {
+        FilterShowActivity activity = (FilterShowActivity) getContext();
+        switch (item.getItemId()) {
+            case R.id.deleteButton:
+                activity.handlePreset(mAction,this,R.id.deleteButton);
+                return true;
+            case R.id.renameButton:
+                activity.handlePreset(mAction,this,R.id.renameButton);
+                return true;
+        }
+        return false;
+    }
+
+
+    @Override
     public void delete() {
         mAdapter.remove(mAction);
     }
+
+    @Override
+    protected void drawBottomRect(Canvas canvas) {
+        super.drawBottomRect(canvas);
+        FilterRepresentation filterRepresentation = mAction.getRepresentation();
+        if (filterRepresentation != null) {
+            if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK
+                    || filterRepresentation.getFilterType() == FilterRepresentation.TYPE_WATERMARK_CATEGORY) {
+                return;
+            }
+            if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_FX) {
+                mPaint.setColor(getResources().getColor(filterRepresentation.getColorId()));
+            } else {
+                mPaint.setColor(
+                        getContext().getResources().getColor(R.color.iconview_bottom_color));
+            }
+            mPaint.setStyle(Paint.Style.FILL);
+            canvas.drawRect(getBitmapBounds().left,
+                    getBitmapBounds().bottom - getBottomRectHeight(),
+                    getBitmapBounds().right,
+                    getBitmapBounds().bottom,
+                    mPaint);
+        }
+    }
+
+    private boolean checkPreset () {
+        FilterRepresentation filterRepresentation = mAction.getRepresentation();
+        if (filterRepresentation != null) {
+            if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 }
diff --git a/src/com/android/gallery3d/filtershow/category/EditorCropPanel.java b/src/com/android/gallery3d/filtershow/category/EditorCropPanel.java
new file mode 100644
index 0000000..37bc862
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/EditorCropPanel.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.editors.EditorCrop;
+
+public class EditorCropPanel extends BasicGeometryPanel {
+    private EditorCrop mEditorCrop;
+
+    private int mSelectPosition = 0;
+
+    private final int[] mCropAspectIds = {
+            R.id.crop_menu_none,
+            R.id.crop_menu_original,
+            R.id.crop_menu_1to1
+    };
+
+    private final int[] mCropDrawableIds = {
+            R.drawable.crop_free_background,
+            R.drawable.crop_original_background,
+            R.drawable.crop_one_background
+    };
+
+    private final int[] mCropTextIds = {
+            R.string.aspectNone_effect,
+            R.string.aspectOriginal_effect,
+            R.string.aspect1to1_effect
+    };
+
+    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            int index = (int) v.getTag();
+            changeSelection(index);
+        }
+    };
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        FilterShowActivity filterShowActivity = (FilterShowActivity) activity;
+        if (filterShowActivity.isReloadByConfigurationChanged()) {
+            mSelectPosition = filterShowActivity.getEditorCropButtonSelect();
+        }
+        mEditorCrop = (EditorCrop) filterShowActivity.getEditor(EditorCrop.ID);
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        if (!isLandscape()) {
+            mEditorName.setText(R.string.crop);
+            mBottomPanel.setVisibility(View.VISIBLE);
+        }
+        mMainView.setBackgroundColor(getContext().getResources().getColor(
+                R.color.edit_actionbar_background));
+
+        mBottomPanel.setVisibility(View.VISIBLE);
+
+        if (mEditorCrop != null) {
+            mEditorCrop.reflectCurrentFilter();
+        }
+
+        highlightIndex(mSelectPosition);
+
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        mApplyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mEditorCrop != null) {
+                    mEditorCrop.finalApplyCalled();
+                }
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+        mExitButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                activity.cancelCurrentFilter();
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+    }
+
+    @Override
+    protected void initButtons() {
+        super.initButtons();
+        int size = mButtons.length;
+        for (int i = 0; i < size; i++) {
+            ImageButton view = mButtons[i];
+            view.setImageDrawable(getResources().getDrawable(mCropDrawableIds[i]));
+            // ues tag to store index.
+            view.setTag(i);
+            view.setOnClickListener(mOnClickListener);
+        }
+    }
+
+    @Override
+    protected void initTexts() {
+        super.initTexts();
+        int size = mTextViews.length;
+        for (int i = 0; i < size; i++) {
+            TextView view = mTextViews[i];
+            view.setText(mCropTextIds[i]);
+        }
+    }
+
+    private void changeSelection(int index) {
+        if (index >= 0 && index < mButtons.length) {
+            mSelectPosition = index;
+            if (mEditorCrop != null) {
+                mEditorCrop.changeCropAspect(mCropAspectIds[index]);
+            }
+            highlightIndex(index);
+        }
+    }
+
+    private void highlightIndex(int index) {
+        int size = mButtons.length;
+        for (int i = 0; i < size; i++) {
+            View view = mButtons[i];
+            view.setSelected(index == i);
+        }
+        size = mTextViews.length;
+        for (int i = 0; i < size; i++) {
+            TextView view = mTextViews[i];
+            view.setTextColor(index == i ?
+                    getResources().getColor(R.color.crop_text_color) :
+                    Color.WHITE);
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        if (mEditorCrop != null) {
+            mEditorCrop.detach();
+        }
+        super.onDetach();
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
+        activity.saveEditorCropState(mSelectPosition);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/GeometryPanel.java b/src/com/android/gallery3d/filtershow/category/GeometryPanel.java
new file mode 100755
index 0000000..e6e0c7a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/GeometryPanel.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+
+import java.util.ArrayList;
+
+public class GeometryPanel extends BasicGeometryPanel {
+
+    ArrayList<FilterRepresentation> mFiltersRepresentations;
+
+    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            int index = (int) v.getTag();
+            if (index >= 0 && index < mButtons.length) {
+                final FilterShowActivity activity = (FilterShowActivity) getActivity();
+                activity.showRepresentation(mFiltersRepresentations.get(index));
+            }
+        }
+    };
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        FiltersManager filtersManager = FiltersManager.getManager();
+        mFiltersRepresentations = filtersManager.getTools();
+        return super.onCreateView(inflater, container, savedInstanceState);
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+    }
+
+    @Override
+    protected void initButtons() {
+        super.initButtons();
+        Resources res = getActivity().getResources();
+        int size = mButtons.length;
+        for (int i = 0; i < size; i++) {
+            ImageButton view = mButtons[i];
+            if (mFiltersRepresentations.size() > 0) {
+                view.setImageDrawable(res.getDrawable(mFiltersRepresentations.get(i).getOverlayId()));
+            }
+            // ues tag to store index.
+            view.setTag(i);
+            view.setOnClickListener(mOnClickListener);
+        }
+    }
+
+    @Override
+    protected void initTexts() {
+        super.initTexts();
+        Resources res = getActivity().getResources();
+        int size = mTextViews.length;
+        for (int i = 0; i < size; i++) {
+            TextView view = mTextViews[i];
+            if (mFiltersRepresentations.size() > 0) {
+                view.setText(res.getString(mFiltersRepresentations.get(i).getTextId()));
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/IconView.java b/src/com/android/gallery3d/filtershow/category/IconView.java
index cba2d79..c952d43 100644
--- a/src/com/android/gallery3d/filtershow/category/IconView.java
+++ b/src/com/android/gallery3d/filtershow/category/IconView.java
@@ -21,17 +21,14 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.graphics.Shader;
 import android.graphics.Typeface;
 import android.util.AttributeSet;
 import android.view.View;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class IconView extends View {
 
@@ -44,6 +41,7 @@
     private int mMargin = 16;
     private int mOrientation = HORIZONTAL;
     private int mTextSize = 32;
+    private int mBottomRectHeight;
     private Rect mTextBounds = new Rect();
     private Bitmap mBitmap;
     private Rect mBitmapBounds;
@@ -69,9 +67,10 @@
     private void setup(Context context) {
         Resources res = getResources();
         mTextColor = res.getColor(R.color.filtershow_categoryview_text);
-        mBackgroundColor = res.getColor(R.color.filtershow_categoryview_background);
+        mBackgroundColor = res.getColor(android.R.color.transparent);
         mMargin = res.getDimensionPixelOffset(R.dimen.category_panel_margin);
         mTextSize = res.getDimensionPixelSize(R.dimen.category_panel_text_size);
+        mBottomRectHeight = res.getDimensionPixelOffset(R.dimen.category_panel_bottom_rect_height);
     }
 
     protected void computeTextPosition(String text) {
@@ -80,7 +79,7 @@
         }
         mPaint.setTextSize(mTextSize);
         if (getOrientation() == VERTICAL) {
-            text = text.toUpperCase();
+//            text = text.toUpperCase();
             // TODO: set this in xml
             mPaint.setTypeface(Typeface.DEFAULT_BOLD);
         }
@@ -108,10 +107,16 @@
             // justify to the left.
             x = mMargin;
         }
-        int y = canvas.getHeight() - 2*mMargin;
+        int y = canvas.getHeight() - mBottomRectHeight / 2 - mMargin / 2;
         canvas.drawText(text, x, y, mPaint);
     }
 
+    private int getTextHeight(Paint paint){
+        paint.setTextSize(mTextSize);
+        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+        return (int)(Math.ceil(fontMetrics.descent - fontMetrics.ascent) + 2);
+    }
+
     protected void drawOutlinedText(Canvas canvas, String text) {
         mPaint.setColor(getBackgroundColor());
         mPaint.setStyle(Paint.Style.STROKE);
@@ -123,6 +128,13 @@
         drawText(canvas, text);
     }
 
+    protected void drawBottomRect(Canvas canvas) {
+    }
+
+    public int getBottomRectHeight() {
+        return mBottomRectHeight;
+    }
+
     public int getOrientation() {
         return mOrientation;
     }
@@ -178,13 +190,14 @@
 
     public void computeBitmapBounds() {
         if (mUseOnlyDrawable) {
-            mBitmapBounds = new Rect(mMargin/2, mMargin, getWidth() - mMargin/2,
-                    getHeight() - mTextSize - 2*mMargin);
+            mBitmapBounds = new Rect(mMargin / 2, mMargin, getWidth() - mMargin / 2,
+                    getHeight() - mTextSize - 2 * mMargin);
         } else {
             if (getOrientation() == VERTICAL && isHalfImage()) {
-                mBitmapBounds = new Rect(mMargin/2, mMargin, getWidth()/2, getHeight());
+                mBitmapBounds = new Rect(mMargin / 2, mMargin, getWidth() / 2, getHeight());
             } else {
-                mBitmapBounds = new Rect(mMargin/2, mMargin, getWidth() - mMargin/2, getHeight());
+                mBitmapBounds = new Rect(mMargin / 2, mMargin, getWidth() - mMargin / 2,
+                        getHeight() - mMargin);
             }
         }
     }
@@ -220,22 +233,7 @@
             canvas.drawBitmap(mBitmap, m, mPaint);
             canvas.restore();
         }
-
-        if (!mUseOnlyDrawable) {
-            int startColor = Color.argb(0, 0, 0, 0);
-            int endColor = Color.argb(200, 0, 0, 0);
-            float start = getHeight() - 2 * mMargin - 2 * mTextSize;
-            float end = getHeight();
-            Shader shader = new LinearGradient(0, start, 0, end, startColor,
-                    endColor, Shader.TileMode.CLAMP);
-            mPaint.setShader(shader);
-            float startGradient = 0;
-            if (getOrientation() == VERTICAL && isHalfImage()) {
-                startGradient = getWidth()/2;
-            }
-            canvas.drawRect(new RectF(startGradient, start, getWidth(), end), mPaint);
-            mPaint.setShader(null);
-        }
+        drawBottomRect(canvas);
         drawOutlinedText(canvas, getText());
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java
old mode 100644
new mode 100755
index 75574c3..505f556
--- a/src/com/android/gallery3d/filtershow/category/MainPanel.java
+++ b/src/com/android/gallery3d/filtershow/category/MainPanel.java
@@ -16,36 +16,74 @@
 
 package com.android.gallery3d.filtershow.category;
 
+import android.content.res.Configuration;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentTransaction;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
+import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+import org.json.JSONObject;
+
+import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.editors.EditorPanel;
+import com.android.gallery3d.filtershow.filters.FiltersManager;
+import com.android.gallery3d.filtershow.filters.HazeBusterActs;
+import com.android.gallery3d.filtershow.filters.SeeStraightActs;
+import com.android.gallery3d.filtershow.filters.SimpleMakeupImageFilter;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.state.StatePanel;
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
 
-public class MainPanel extends Fragment {
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class MainPanel extends Fragment implements BottomPanel.BottomPanelDelegate {
 
     private static final String LOGTAG = "MainPanel";
 
     private LinearLayout mMainView;
+    private View mBottomPanelView;
     private ImageButton looksButton;
     private ImageButton bordersButton;
     private ImageButton geometryButton;
     private ImageButton filtersButton;
+    private ImageButton dualCamButton;
+    private ImageButton makeupButton;
+    private ImageButton trueScannerButton;
+    private ImageButton hazeBusterButton;
+    private ImageButton seeStraightButton;
+    private ImageButton truePortraitButton;
+    private ImageButton waterMarkButton;
 
     public static final String FRAGMENT_TAG = "MainPanel";
+    public static final String EDITOR_TAG = "coming-from-editor-panel";
     public static final int LOOKS = 0;
     public static final int BORDERS = 1;
     public static final int GEOMETRY = 2;
     public static final int FILTERS = 3;
-    public static final int VERSIONS = 4;
+    public static final int MAKEUP = 4;
+    public static final int DUALCAM = 5;
+    public static final int VERSIONS = 6;
+    public static final int TRUESCANNER = 7;
+    public static final int HAZEBUSTER = 8;
+    public static final int SEESTRAIGHT = 9;
+    public static final int TRUEPORTRAIT = 10;
+    public static final int WATERMARK = 11;
 
     private int mCurrentSelected = -1;
     private int mPreviousToggleVersions = -1;
@@ -72,6 +110,42 @@
                 filtersButton.setSelected(value);
                 break;
             }
+            case MAKEUP: {
+                if(makeupButton != null) {
+                    makeupButton.setSelected(value);
+                }
+                break;
+            }
+            case DUALCAM: {
+                dualCamButton.setSelected(value);
+                break;
+            }
+            case TRUEPORTRAIT: {
+                truePortraitButton.setSelected(value);
+                break;
+            }
+            case TRUESCANNER: {
+                if (trueScannerButton != null) {
+                    trueScannerButton.setSelected(value);
+                }
+                break;
+            }
+            case HAZEBUSTER: {
+                if (hazeBusterButton != null) {
+                    hazeBusterButton.setSelected(value);
+                }
+                break;
+            }
+            case SEESTRAIGHT: {
+                if (seeStraightButton != null) {
+                    seeStraightButton.setSelected(value);
+                }
+                break;
+            }
+            case WATERMARK: {
+                waterMarkButton.setSelected(value);
+                break;
+            }
         }
     }
 
@@ -88,16 +162,87 @@
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                             Bundle savedInstanceState) {
-
+            Bundle savedInstanceState) {
         mMainView = (LinearLayout) inflater.inflate(
                 R.layout.filtershow_main_panel, null, false);
 
-        looksButton = (ImageButton) mMainView.findViewById(R.id.fxButton);
-        bordersButton = (ImageButton) mMainView.findViewById(R.id.borderButton);
-        geometryButton = (ImageButton) mMainView.findViewById(R.id.geometryButton);
-        filtersButton = (ImageButton) mMainView.findViewById(R.id.colorsButton);
+        getBottomPanelView(inflater);
+        initBottomPanel();
 
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
+        showPanel(activity.getCurrentPanel());
+        return mMainView;
+    }
+
+    private void initBottomPanel() {
+        BottomPanel panel = new BottomPanel();
+        panel.setBottomPanelDelegate(this);
+        setActionFragment(panel, BottomPanel.FRAGMENT_TAG);
+    }
+
+    @Override
+    public View getBottomPanelView(LayoutInflater inflater) {
+        if (mBottomPanelView != null) {
+            return mBottomPanelView;
+        }
+
+        LinearLayout bottomPanel = (LinearLayout) inflater.inflate(
+                R.layout.filtershow_bottom_panel, null, false);
+
+        looksButton = (ImageButton) bottomPanel.findViewById(R.id.fxButton);
+        bordersButton = (ImageButton) bottomPanel.findViewById(R.id.borderButton);
+        geometryButton = (ImageButton) bottomPanel.findViewById(R.id.geometryButton);
+        filtersButton = (ImageButton) bottomPanel.findViewById(R.id.colorsButton);
+        dualCamButton = (ImageButton) bottomPanel.findViewById(R.id.dualCamButton);
+
+        if (SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
+            makeupButton = (ImageButton) bottomPanel.findViewById(R.id.makeupButton);
+            makeupButton.setVisibility(View.VISIBLE);
+        }
+
+        if (makeupButton != null) {
+            makeupButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    showPanel(MAKEUP);
+                }
+            });
+        }
+        trueScannerButton = (ImageButton) bottomPanel.findViewById(R.id.trueScannerButton);
+        if (!TrueScannerActs.isTrueScannerEnabled()) {
+            trueScannerButton.setVisibility(View.GONE);
+        }
+
+        hazeBusterButton = (ImageButton) bottomPanel.findViewById(R.id.hazeBusterButton);
+        if (!HazeBusterActs.isHazeBusterEnabled()) {
+            hazeBusterButton.setVisibility(View.GONE);
+        }
+
+        seeStraightButton = (ImageButton) bottomPanel.findViewById(R.id.seeStraightButton);
+        if (!SeeStraightActs.isSeeStraightEnabled()) {
+            seeStraightButton.setVisibility(View.GONE);
+        }
+
+        truePortraitButton = (ImageButton) bottomPanel.findViewById(R.id.truePortraitButton);
+        if(!TruePortraitNativeEngine.getInstance().isLibLoaded()) {
+            truePortraitButton.setVisibility(View.GONE);
+        }
+
+        waterMarkButton = (ImageButton) bottomPanel.findViewById(R.id.waterMarkButton);
+
+        waterMarkButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (MasterImage.getImage().getHistory().getItem(1) == null) {
+                    waterMarkButton.setVisibility(View.VISIBLE);
+                    showPanel(WATERMARK);
+                } else {
+                    Toast.makeText(getActivity(), "Watermark only support single edit",
+                            Toast.LENGTH_SHORT).show();
+                    waterMarkButton.setVisibility(View.GONE);
+                }
+            }
+        });
         looksButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
@@ -122,11 +267,85 @@
                 showPanel(FILTERS);
             }
         });
+        dualCamButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Context context = getActivity();
+                boolean skipIntro = GalleryUtils.getBooleanPref(context,
+                        context.getString(R.string.pref_dualcam_intro_show_key), false);
+                if (skipIntro) {
+                    showPanel(DUALCAM);
+                } else {
+                    DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
+                            R.string.dual_camera_effects, R.string.dual_camera_effects_intro,
+                            R.string.pref_dualcam_intro_show_key);
+                    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                        @Override
+                        public void onDismiss(DialogInterface dialog) {
+                            showPanel(DUALCAM);
+                        }
+                    });
+                    dialog.show(getFragmentManager(), "dualcam_intro");
+                }
+            }
+        });
 
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        showImageStatePanel(activity.isShowingImageStatePanel());
-        showPanel(activity.getCurrentPanel());
-        return mMainView;
+        truePortraitButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(final View v) {
+                Context context = getActivity();
+                boolean skipIntro = GalleryUtils.getBooleanPref(context,
+                        context.getString(R.string.pref_trueportrait_intro_show_key), false);
+                final boolean facesDetected = TruePortraitNativeEngine.getInstance().facesDetected();
+                if(skipIntro && facesDetected) {
+                    showPanel(TRUEPORTRAIT);
+                } else if(!skipIntro) {
+                    DoNotShowAgainDialog dialog = new DoNotShowAgainDialog(
+                            R.string.trueportrait, R.string.trueportrait_intro,
+                            R.string.pref_trueportrait_intro_show_key);
+                    dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
+                        @Override
+                        public void onDismiss(DialogInterface dialog) {
+                            if(facesDetected) {
+                                showPanel(TRUEPORTRAIT);
+                            } else {
+                                v.setEnabled(false);
+                                TruePortraitNativeEngine.getInstance().showNoFaceDetectedDialog(getFragmentManager());
+                            }
+                        }
+                    });
+                    dialog.show(getFragmentManager(), "trueportrait_intro");
+                } else {
+                    v.setEnabled(false);
+                    TruePortraitNativeEngine.getInstance().showNoFaceDetectedDialog(getFragmentManager());
+                }
+            }
+        });
+
+        trueScannerButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+
+                showPanel(TRUESCANNER);
+            }
+        });
+
+        hazeBusterButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showPanel(HAZEBUSTER);
+            }
+        });
+
+        seeStraightButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showPanel(SEESTRAIGHT);
+            }
+        });
+
+        mBottomPanelView = bottomPanel;
+        return bottomPanel;
     }
 
     private boolean isRightAnimation(int newPos) {
@@ -136,13 +355,35 @@
         return true;
     }
 
-    private void setCategoryFragment(CategoryPanel category, boolean fromRight) {
+    private void setActionFragment(Fragment actionFragment, String tag) {
         FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
+        transaction.replace(R.id.bottom_panel_container, actionFragment, tag);
+        transaction.commitAllowingStateLoss();
+    }
+
+    public boolean hasEditorPanel() {
+        Fragment fragment = getChildFragmentManager().findFragmentByTag(EditorPanel.FRAGMENT_TAG);
+        return (fragment != null);
+    }
+
+    public void setEditorPanelFragment(Fragment editorFragment) {
+        setActionFragment(editorFragment, EditorPanel.FRAGMENT_TAG);
+    }
+
+    public void removeEditorPanelFragment() {
+        // use bottom panel replace editor panel.
+        initBottomPanel();
+    }
+
+    private void setCategoryFragment(Fragment category, boolean fromRight) {
+        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
         if (fromRight) {
             transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right);
         } else {
             transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left);
         }
+        activity.setActionBar();
         transaction.replace(R.id.category_panel_container, category, CategoryPanel.FRAGMENT_TAG);
         transaction.commitAllowingStateLoss();
     }
@@ -173,6 +414,19 @@
         selection(mCurrentSelected, true);
     }
 
+    public void loadCategoryMakeupPanel() {
+        if (makeupButton == null) {
+            return;
+        }
+        boolean fromRight = isRightAnimation(MAKEUP);
+        selection(mCurrentSelected, false);
+        CategoryPanel categoryPanel = new CategoryPanel();
+        categoryPanel.setAdapter(MAKEUP);
+        setCategoryFragment(categoryPanel, fromRight);
+        mCurrentSelected = MAKEUP;
+        selection(mCurrentSelected, true);
+    }
+
     public void loadCategoryGeometryPanel() {
         if (mCurrentSelected == GEOMETRY) {
             return;
@@ -182,13 +436,60 @@
         }
         boolean fromRight = isRightAnimation(GEOMETRY);
         selection(mCurrentSelected, false);
-        CategoryPanel categoryPanel = new CategoryPanel();
-        categoryPanel.setAdapter(GEOMETRY);
+        GeometryPanel categoryPanel = new GeometryPanel();
         setCategoryFragment(categoryPanel, fromRight);
         mCurrentSelected = GEOMETRY;
         selection(mCurrentSelected, true);
     }
 
+    public void loadCategoryTrueScannerPanel() {
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        CategoryAdapter adapter = activity.getCategoryTrueScannerAdapter();
+        if (adapter.getCount() == 1) {
+            activity.showRepresentation(adapter.getItem(0).getRepresentation());
+        } else {
+            boolean fromRight = isRightAnimation(TRUESCANNER);
+            selection(mCurrentSelected, false);
+            CategoryPanel categoryPanel = new CategoryPanel();
+            categoryPanel.setAdapter(TRUESCANNER);
+            setCategoryFragment(categoryPanel, fromRight);
+            mCurrentSelected = TRUESCANNER;
+            selection(mCurrentSelected, true);
+        }
+    }
+
+    public void loadCategoryHazeBusterPanel() {
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        CategoryAdapter adapter = activity.getCategoryHazeBusterAdapter();
+        if (adapter.getCount() == 1) {
+            activity.showRepresentation(adapter.getItem(0).getRepresentation());
+        } else {
+            boolean fromRight = isRightAnimation(HAZEBUSTER);
+            selection(mCurrentSelected, false);
+            CategoryPanel categoryPanel = new CategoryPanel();
+            categoryPanel.setAdapter(HAZEBUSTER);
+            setCategoryFragment(categoryPanel, fromRight);
+            mCurrentSelected = HAZEBUSTER;
+            selection(mCurrentSelected, true);
+        }
+    }
+
+    public void loadCategorySeeStraightPanel() {
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        CategoryAdapter adapter = activity.getCategorySeeStraightAdapter();
+        if (adapter.getCount() == 1) {
+            activity.showRepresentation(adapter.getItem(0).getRepresentation());
+        } else {
+            boolean fromRight = isRightAnimation(SEESTRAIGHT);
+            selection(mCurrentSelected, false);
+            CategoryPanel categoryPanel = new CategoryPanel();
+            categoryPanel.setAdapter(SEESTRAIGHT);
+            setCategoryFragment(categoryPanel, fromRight);
+            mCurrentSelected = SEESTRAIGHT;
+            selection(mCurrentSelected, true);
+        }
+    }
+
     public void loadCategoryFiltersPanel() {
         if (mCurrentSelected == FILTERS) {
             return;
@@ -217,7 +518,125 @@
         selection(mCurrentSelected, true);
     }
 
+    public void loadCategoryDualCamPanel() {
+        if (mCurrentSelected == DUALCAM) {
+            return;
+        }
+        boolean fromRight = isRightAnimation(DUALCAM);
+        selection(mCurrentSelected, false);
+        CategoryPanel categoryPanel = new CategoryPanel();
+        categoryPanel.setAdapter(DUALCAM);
+        setCategoryFragment(categoryPanel, fromRight);
+        mCurrentSelected = DUALCAM;
+        selection(mCurrentSelected, true);
+    }
+
+    public void loadCategoryTruePortraitPanel() {
+        if (mCurrentSelected == TRUEPORTRAIT) {
+            return;
+        }
+        boolean fromRight = isRightAnimation(TRUEPORTRAIT);
+        selection(mCurrentSelected, false);
+        CategoryPanel categoryPanel = new CategoryPanel();
+        categoryPanel.setAdapter(TRUEPORTRAIT);
+        setCategoryFragment(categoryPanel, fromRight);
+        mCurrentSelected = TRUEPORTRAIT;
+        selection(mCurrentSelected, true);
+    }
+
+    public void loadWaterMarkPanel() {
+        if (mCurrentSelected == WATERMARK) {
+            return;
+        }
+        boolean fromRight = isRightAnimation(WATERMARK);
+        selection(mCurrentSelected, false);
+        CategoryPanel categoryPanel = new CategoryPanel();
+        categoryPanel.setAdapter(WATERMARK);
+        setCategoryFragment(categoryPanel, fromRight);
+        mCurrentSelected = WATERMARK;
+        selection(mCurrentSelected, true);
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+//        String url = "http://api.map.baidu.com/location/ip?ak=PR0TaSQODfSbVr7hkcNF4NkAYEixoxSy&coor=bd09ll";
+        String url = "";
+        new AsyncTask<String, Void, String>() {
+            @Override
+            protected String doInBackground(String... strings) {
+                HttpURLConnection connection = null;
+                String location = "";
+                try {
+                    URL url = new URL(strings[0]);
+                    connection = (HttpURLConnection) url.openConnection();
+                    connection.setRequestMethod("GET");
+                    connection.setRequestProperty("Charset", "UTF-8");
+                    connection.connect();
+                    if (connection.getResponseCode() == 200) {
+                        String result = WaterMarkView.convertStream2String(connection.getInputStream());
+                        JSONObject resultJson = new JSONObject(result);
+                        location = resultJson.getJSONObject("content").getString("address");
+                        if (!TextUtils.isEmpty(location)) {
+                            getWeather(activity, location);
+                        }
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    if (connection != null) {
+                        connection.disconnect();
+                    }
+                }
+                return location;
+            }
+
+            @Override
+            protected void onPostExecute(String s) {
+                activity.setLocation(s);
+            }
+        }.execute(url);
+    }
+
+    private void getWeather(final FilterShowActivity activity, String city) {
+//        String url = "http://api.map.baidu.com/telematics/v3/weather?location="
+//                + city + "&output=json&ak=PR0TaSQODfSbVr7hkcNF4NkAYEixoxSy";
+        String url = "";
+        new AsyncTask<String, Void, String>() {
+            @Override
+            protected String doInBackground(String... strings) {
+                HttpURLConnection connection = null;
+                String temperature = "";
+                try {
+                    URL url = new URL(strings[0]);
+                    connection = (HttpURLConnection) url.openConnection();
+                    connection.setRequestMethod("GET");
+                    connection.setRequestProperty("Charset", "UTF-8");
+                    connection.connect();
+                    if (connection.getResponseCode() == 200) {
+                        String result = WaterMarkView.convertStream2String(connection.getInputStream());
+                        JSONObject resultJson = new JSONObject(result);
+                        String weather = resultJson.getJSONArray("results").getJSONObject(0).getJSONArray("weather_data").getJSONObject(0).getString("date");
+                        temperature = weather.substring(weather.indexOf(":")+1, weather.indexOf(")"));
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    if (connection != null) {
+                        connection.disconnect();
+                    }
+                }
+                return temperature;
+            }
+
+            @Override
+            protected void onPostExecute(String s) {
+                activity.setTemperature(s);
+            }
+        }.execute(url);
+    }
+
     public void showPanel(int currentPanel) {
+        FilterShowActivity activity = (FilterShowActivity) getActivity();
+        if (null == activity) {
+            return;
+        }
         switch (currentPanel) {
             case LOOKS: {
                 loadCategoryLookPanel(false);
@@ -235,10 +654,43 @@
                 loadCategoryFiltersPanel();
                 break;
             }
+            case DUALCAM: {
+                loadCategoryDualCamPanel();
+                break;
+            }
+            case TRUESCANNER: {
+                loadCategoryTrueScannerPanel();
+                break;
+            }
+            case HAZEBUSTER: {
+                loadCategoryHazeBusterPanel();
+                break;
+            }
+            case SEESTRAIGHT: {
+                loadCategorySeeStraightPanel();
+                break;
+            }
             case VERSIONS: {
                 loadCategoryVersionsPanel();
                 break;
             }
+            case MAKEUP: {
+                loadCategoryMakeupPanel();
+                break;
+            }
+            case TRUEPORTRAIT: {
+                loadCategoryTruePortraitPanel();
+                break;
+            }
+            case WATERMARK: {
+                loadWaterMarkPanel();
+                break;
+            }
+        }
+        if (currentPanel > 0) {
+            activity.adjustCompareButton(true);
+        } else {
+            activity.adjustCompareButton(false);
         }
     }
 
@@ -295,4 +747,16 @@
         showPanel(currentPanel);
         transaction.commit();
     }
+
+    public void showDualCameraButton(boolean visible) {
+        if (dualCamButton != null) {
+            dualCamButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    public void showWatermarkButton(boolean visible) {
+        if (waterMarkButton != null) {
+            waterMarkButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/category/StraightenPanel.java b/src/com/android/gallery3d/filtershow/category/StraightenPanel.java
new file mode 100644
index 0000000..6d6919f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/StraightenPanel.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.editors.Editor;
+
+import org.codeaurora.gallery.R;
+
+public class StraightenPanel extends BasicGeometryPanel {
+    public static final String EDITOR_ID = "editor_id";
+    public static final String EDITOR_NAME = "editor_name";
+    public static final int NO_EDITOR = -1;
+    private Editor mEditor;
+    private int mEditorID = NO_EDITOR;
+    private String mName;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    private void initArguments(Bundle arguments) {
+        if (arguments != null) {
+            mEditorID = arguments.getInt(EDITOR_ID);
+            mName = arguments.getString(EDITOR_NAME);
+        }
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        initArguments(getArguments());
+        if (mEditorID != NO_EDITOR) {
+            FilterShowActivity filterShowActivity = (FilterShowActivity) activity;
+            mEditor = filterShowActivity.getEditor(mEditorID);
+            if (mEditor != null) {
+                mEditor.attach();
+            }
+        }
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        if (mName != null) {
+            mEditorName.setText(mName);
+        }
+
+        mBottomPanel.setVisibility(View.VISIBLE);
+
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        mExitButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                activity.cancelCurrentFilter();
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+        mApplyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mEditor != null) {
+                    mEditor.finalApplyCalled();
+                }
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+    }
+
+    @Override
+    protected void initPanels() {
+        super.initPanels();
+        for (View view : mPanels) {
+            view.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        if (mEditor != null) {
+            mEditor.detach();
+        }
+        super.onDetach();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/TruePortraitMaskEditorPanel.java b/src/com/android/gallery3d/filtershow/category/TruePortraitMaskEditorPanel.java
new file mode 100644
index 0000000..891966c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/TruePortraitMaskEditorPanel.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+
+import android.content.Context;
+import android.os.Bundle;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitMask;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
+
+public class TruePortraitMaskEditorPanel extends Fragment {
+    private View mMainView;
+    private EditorTruePortraitMask mEditor;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        FilterShowActivity filterShowActivity = (FilterShowActivity) context;
+        mEditor = (EditorTruePortraitMask) filterShowActivity.getEditor(EditorTruePortraitMask.ID);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mMainView = inflater.inflate(R.layout.filtershow_trueportrait_editor_panel, container, false);
+        if (mEditor != null) {
+            mEditor.setUpEditorUI(mMainView, null);
+        }
+        return mMainView;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        Context context = getActivity();
+        boolean skipIntro = GalleryUtils.getBooleanPref(context,
+                context.getString(R.string.pref_trueportrait_edit_intro_show_key), false);
+        if(!skipIntro) {
+            FragmentManager fm = getFragmentManager();
+            DoNotShowAgainDialog dialog =
+                    (DoNotShowAgainDialog) fm.findFragmentByTag("trueportrait_edit_intro");
+            if(dialog == null) {
+                dialog = new DoNotShowAgainDialog(
+                        R.string.trueportrait_touch_up, R.string.trueportrait_edit_intro,
+                        R.string.pref_trueportrait_edit_intro_show_key);
+                dialog.setCancelable(false);
+                dialog.show(fm, "trueportrait_edit_intro");
+            } else if (dialog.isDetached()) {
+                FragmentTransaction ft = fm.beginTransaction();
+                ft.attach(dialog);
+                ft.commit();
+            } else if (dialog.isHidden()) {
+                FragmentTransaction ft = fm.beginTransaction();
+                ft.show(dialog);
+                ft.commit();
+            }
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        if (mEditor != null) {
+            mEditor.detach();
+        }
+        super.onDetach();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/TrueScannerPanel.java b/src/com/android/gallery3d/filtershow/category/TrueScannerPanel.java
new file mode 100644
index 0000000..97c8c4b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/TrueScannerPanel.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.category;
+
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.view.View;
+import androidx.annotation.Nullable;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+
+import org.codeaurora.gallery.R;
+
+public class TrueScannerPanel extends BasicGeometryPanel {
+    private TrueScannerEditor mTrueScannerEditor;
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        FilterShowActivity filterShowActivity = (FilterShowActivity) activity;
+        mTrueScannerEditor = (TrueScannerEditor) filterShowActivity.getEditor(TrueScannerEditor.ID);
+    }
+
+    @Override
+    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        mEditorName.setText(R.string.truescanner);
+
+        mBottomPanel.setVisibility(View.VISIBLE);
+        final FilterShowActivity activity = (FilterShowActivity) getActivity();
+        if (mTrueScannerEditor == null) {
+            mTrueScannerEditor = (TrueScannerEditor) activity.getEditor(TrueScannerEditor.ID);
+        }
+        if (mTrueScannerEditor != null) {
+            mTrueScannerEditor.initCords();
+        }
+        mExitButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                activity.cancelCurrentFilter();
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+        mApplyButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mTrueScannerEditor != null) {
+                    mTrueScannerEditor.finalApplyCalled();
+                }
+                activity.backToMain();
+                activity.setActionBar();
+            }
+        });
+    }
+
+    @Override
+    protected void initPanels() {
+        super.initPanels();
+        int size = mPanels.length;
+        for (int i = 0; i < size; i++) {
+            View view = mPanels[i];
+            view.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onDetach() {
+        if (mTrueScannerEditor != null) {
+            mTrueScannerEditor.detach();
+        }
+        super.onDetach();
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java b/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java
new file mode 100644
index 0000000..86a8a76
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/WaterMarkTimeView.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import org.codeaurora.gallery.R;
+
+public class WaterMarkTimeView extends WaterMarkView {
+    public WaterMarkTimeView(Context context) {
+        super(context);
+    }
+    public WaterMarkTimeView(Context context, Drawable drawable, int type) {
+        super(context);
+        init(context, drawable, type);
+    }
+
+    private void init(Context context, Drawable drawable, int type) {
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        widthScreen = dm.widthPixels;
+        heightScreen = dm.heightPixels;
+        initView(context, drawable, type);
+    }
+
+    private void initView(Context context, Drawable drawable, int type) {
+        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        FrameLayout layout = (FrameLayout)inflater.inflate(R.layout.filtershow_watermark, this, true);
+        mImageView = (ImageView) layout.findViewById(R.id.image);
+        mMarkDrawable = drawable;
+        mImageView.setBackground(drawable);
+        markLayout = (FrameLayout) layout.findViewById(R.id.root_layout);
+
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/category/WaterMarkView.java b/src/com/android/gallery3d/filtershow/category/WaterMarkView.java
new file mode 100644
index 0000000..36ba392
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/category/WaterMarkView.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.filtershow.category;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+import org.codeaurora.gallery.R;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class WaterMarkView extends FrameLayout {
+    private static final int NONE = 0;
+    private static final int DRAG = 1;
+    private static final int ZOOM = 2;
+
+    private int mode = NONE;
+
+    private float x_down = 0;
+    private float y_down = 0;
+    private float moveX;
+    private float moveY;
+    private float scaleMoveX = 0;
+    private float scaleMoveY = 0;
+    private float finalMoveX;
+    private float finalMoveY;
+    private float rotation;
+    private float oldRotation = 0;
+    private float lastRotation = 0;
+    private float finalRotation;
+    private float scale = 1f;
+    private float lastScale = 1f;
+    private float oldDist = 1f;
+    private float newDist;
+    private Rect imageBounds;
+    protected int widthScreen;
+    protected int heightScreen;
+    private String text;
+
+    private EditText mEditText;
+    protected FrameLayout markLayout;
+    protected Drawable mMarkDrawable;
+    protected ImageView mImageView;
+
+    //control the bounds of the watermark
+    private float markLeft;
+    private float markTop;
+    private float markRight;
+    private float markBottom;
+
+    private GeometryMathUtils.GeometryHolder mGeometry;
+    private Matrix mDisplaySegPointsMatrix;
+    private Matrix oldImageToScreenMatrix;
+    private RectF markLayoutRect = new RectF(markLeft, markTop, markRight, markBottom);
+    private int newWidth;
+    private int newHeight;
+    private int oldWidth;
+    private int oldHeight;
+    private boolean sizeChanged = false;
+    public boolean mTouchable;
+
+    public WaterMarkView(Context context) {
+        super(context);
+    }
+
+    public WaterMarkView(Context context, Drawable drawable, String text) {
+        super(context);
+        init(context, drawable, text);
+    }
+
+    private void init(Context context, Drawable drawable, String text) {
+        updateScreenSize();
+        initView(context, drawable, text);
+
+        MasterImage.getImage().addWaterMark(this);
+        mGeometry = new GeometryMathUtils.GeometryHolder();
+        imageBounds = MasterImage.getImage().getImageBounds();
+    }
+
+    private void initView(Context context, Drawable drawable, String text) {
+        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        FrameLayout layout = (FrameLayout)inflater.inflate(R.layout.filtershow_watermark, this, true);
+        mImageView = (ImageView) layout.findViewById(R.id.image);
+        mMarkDrawable = drawable;
+        mImageView.setBackground(drawable);
+        markLayout = (FrameLayout) layout.findViewById(R.id.root_layout);
+        mEditText = (EditText) layout.findViewById(R.id.edit);
+        mEditText.setHint(text);
+        mEditText.addTextChangedListener(new TextWatcher() {
+            @Override
+            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+            }
+
+            @Override
+            public void onTextChanged(CharSequence s, int start, int before, int count) {
+                setTextContent(s.toString());
+            }
+
+            @Override
+            public void afterTextChanged(Editable s) {
+
+            }
+        });
+        initMarkBounds();
+    }
+
+    public void clearEditTextCursor() {
+        mEditText.setCursorVisible(false);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        if (oldw == 0 || oldh == 0) {
+            Bitmap mBitmap = MasterImage.getImage().getHighresImage();
+            oldImageToScreenMatrix = MasterImage.getImage().computeImageToScreen(mBitmap, 0, false);
+            return;
+        }
+        newWidth = w;
+        newHeight = h;
+        oldWidth = oldw;
+        oldHeight = oldh;
+        sizeChanged = true;
+        updateScreenSize();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        if (rotation > 0 || rotation < 0) {
+            finalRotation = lastRotation + rotation;
+            markLayout.setRotation(finalRotation);
+        }
+        if (scale > 0) {
+            markLayout.setScaleX(scale);
+            markLayout.setScaleY(scale);
+        }
+        if (moveX != 0 || moveY != 0) {
+            finalMoveX = markLeft + moveX - scaleMoveX;
+            finalMoveY = markTop + moveY - scaleMoveY;
+            markLayout.setTranslationX(finalMoveX);
+            markLayout.setTranslationY(finalMoveY);
+        }
+        super.onLayout(changed, l, t, r, b);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (!mTouchable) return false;
+        switch (event.getAction() & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                markLayout.setFocusable(true);
+                markLayout.setFocusableInTouchMode(true);
+                mEditText.clearFocus();
+                mode = isOutMark(event) ? NONE : DRAG;
+                x_down = event.getX();
+                y_down = event.getY();
+                break;
+            case MotionEvent.ACTION_POINTER_DOWN:
+                mode = isOutMark(event) ? NONE : ZOOM;
+                if (mode == ZOOM) {
+                    markLayout.setBackgroundResource(R.drawable.grid_pressed);
+                }
+                oldDist = spacing(event);
+                oldRotation = rotation(event);
+                break;
+            case MotionEvent.ACTION_MOVE:
+                switch (mode) {
+                    case ZOOM:
+                        rotation = rotation(event) - oldRotation;
+                        newDist = spacing(event);
+                        scale = (newDist / oldDist) * lastScale;
+                        break;
+                    case DRAG:
+                        if (!outBound(event.getX(), event.getY())) {
+                            moveX = event.getX() - x_down;
+                            moveY = event.getY() - y_down;
+                        }
+                        break;
+                    case NONE:
+                        break;
+                }
+                requestLayout();
+                break;
+            case MotionEvent.ACTION_UP:
+            case MotionEvent.ACTION_POINTER_UP:
+                switch (mode) {
+                    case ZOOM:
+                        lastRotation += rotation;
+                        lastScale = scale;
+                        float thisScale = newDist / oldDist;
+                        if (thisScale > 0 && thisScale != 1f) {
+                            float halfNewWidth = (markLayout.getMeasuredWidth() * scale) / 2;
+                            float halfNewHeight = (markLayout.getMeasuredHeight() * scale) / 2;
+                            float l, t, r, b;
+                            l = markLeft;
+                            t = markTop;
+                            r = markRight;
+                            b = markBottom;
+                            markLeft = getMid(l, r) - halfNewWidth;
+                            markTop = getMid(t, b) - halfNewHeight;
+                            markRight = getMid(l, r) + halfNewWidth;
+                            markBottom = getMid(t, b) + halfNewHeight;
+                            updateMarkLayoutRect();
+                            scaleMoveX = markLayout.getMeasuredWidth()/2 - halfNewWidth;
+                            scaleMoveY = markLayout.getMeasuredHeight()/2 - halfNewHeight;
+                        }
+                        markLayout.setBackground(null);
+                        break;
+                    case DRAG:
+                        if (moveX != 0) {
+                            markLeft += moveX;
+                            markRight += moveX;
+                        }
+                        if (moveY != 0) {
+                            markTop += moveY;
+                            markBottom += moveY;
+                        }
+                        updateMarkLayoutRect();
+                        break;
+                }
+                moveX = 0;
+                moveY = 0;
+                rotation = 0;
+                mode = NONE;
+                break;
+        }
+        return true;
+    }
+
+    private boolean outBound(float x, float y) {
+        if (imageBounds == null) {
+            return true;
+        }
+        return x < (imageBounds.left < 0 ? 0 : imageBounds.left) + x_down - markLeft
+                || x > (imageBounds.right > widthScreen ? widthScreen : imageBounds.right) + x_down - markRight
+                || y < (imageBounds.top < 0 ? 0 : imageBounds.top) + y_down - markTop
+                || y > (imageBounds.bottom > heightScreen ? heightScreen : imageBounds.bottom) + y_down - markBottom;
+    }
+
+    private boolean isOutMark(MotionEvent event) {
+        switch (event.getAction() & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN:
+                float x = event.getX();
+                float y = event.getY();
+                return x < markLeft || x > markRight || y < markTop || y > markBottom;
+            case MotionEvent.ACTION_POINTER_DOWN:
+                float x0 = event.getX(0);
+                float y0 = event.getY(0);
+                float x1 = event.getX(1);
+                float y1 = event.getY(1);
+                return (x0 < markLeft || x0 > markRight || y0 < markTop || y0 > markBottom)
+                        &&(x1 < markLeft || x1 > markRight || y1 < markTop || y1 > markBottom);
+        }
+        return false;
+    }
+    private float getMid(float x1, float x2) {
+        return (x1 + x2) / 2;
+    }
+
+    private float spacing(MotionEvent event) {
+        float x = event.getX(0) - event.getX(1);
+        float y = event.getY(0) - event.getY(1);
+        return (float) Math.sqrt(x * x + y * y);
+    }
+
+    private float rotation(MotionEvent event) {
+        double delta_x = (event.getX(0) - event.getX(1));
+        double delta_y = (event.getY(0) - event.getY(1));
+        double radians = Math.atan2(delta_y, delta_x);
+        return (float) Math.toDegrees(radians);
+    }
+
+    protected void initMarkBounds() {
+        if (widthScreen > heightScreen) {
+            if (MasterImage.getImage().getFilteredImage().getWidth() >
+                    MasterImage.getImage().getFilteredImage().getHeight()) {
+                markLeft = dip2px(getContext(), 50);
+            } else {
+                markLeft = dip2px(getContext(), 200);
+            }
+            markTop = dip2px(getContext(), 35);
+            markBottom = markTop + dip2px(getContext(), 100);
+            markRight = markLeft + dip2px(getContext(), 80);
+        } else {
+            markLeft = dip2px(getContext(), 50);
+            if (MasterImage.getImage().getFilteredImage().getWidth() >
+                    MasterImage.getImage().getFilteredImage().getHeight()) {
+                markTop = dip2px(getContext(), 200);
+            } else {
+                markTop = dip2px(getContext(), 70);
+            }
+            markBottom = markTop + dip2px(getContext(), 100);
+            markRight = markLeft + dip2px(getContext(), 80);
+        }
+        updateMarkLayoutRect();
+        markLayout.setTranslationX(markLeft);
+        markLayout.setTranslationY(markTop);
+    }
+
+    private void updateMarkLayoutRect() {
+        markLayoutRect.left = markLeft;
+        markLayoutRect.right = markRight;
+        markLayoutRect.top = markTop;
+        markLayoutRect.bottom = markBottom;
+    }
+
+    private void updateScreenSize() {
+        DisplayMetrics dm = getResources().getDisplayMetrics();
+        widthScreen = dm.widthPixels;
+        heightScreen = dm.heightPixels;
+    }
+
+    /**
+     * save view as a bitmap
+     */
+    public Bitmap creatNewPhoto() {
+        // get current view bitmap
+        markLayout.buildDrawingCache();
+        Bitmap bitmap = markLayout.getDrawingCache();
+
+        Bitmap bmp = duplicateBitmap(bitmap);
+//        if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); }
+        // clear the cache
+        markLayout.setDrawingCacheEnabled(false);
+        return bmp;
+    }
+
+    private Bitmap duplicateBitmap(Bitmap bmpSrc) {
+        if (null == bmpSrc) {
+            return null;
+        }
+
+        Rect r = MasterImage.getImage().getImageBounds();
+        Bitmap b = MasterImage.getImage().getFilteredImage();
+        Bitmap bmpDest = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888);
+        if (null != bmpDest) {
+            Canvas canvas = new Canvas(bmpDest);
+            Matrix m = new Matrix();
+            m.setScale(scale, scale);
+            m.postRotate(getFinalRotation());
+            if (b.getWidth() < b.getHeight()) {
+                int deltaX = (r.width() - widthScreen) / 2;
+                m.postTranslate((int) markLeft + deltaX, (int) markTop);
+            } else {
+                int deltaY = (r.height() - heightScreen) / 2;
+                m.postTranslate((int) markLeft, (int) markTop + deltaY);
+            }
+            canvas.drawBitmap(bmpSrc, m, null);
+        }
+        return bmpDest;
+    }
+
+    private int dip2px(Context context, float dipValue) {
+        final float scale = context.getResources().getDisplayMetrics().density;
+        return (int) (dipValue * scale + 0.5f);
+    }
+
+    /**
+     * @param left margin left
+     * @param top margin top
+     * @param right margin right
+     * @param bottom margin bottom
+     * @param gravity gravity value
+     * @param isDipValue true means the values of left top right bottom are dip not px
+     */
+    public void setTextPosition(int left, int top, int right, int bottom,
+                              int gravity, boolean isDipValue) {
+        FrameLayout.LayoutParams params =
+                new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT);
+        if (isDipValue) {
+            left = dip2px(getContext(), left);
+            top = dip2px(getContext(), top);
+            right = dip2px(getContext(), right);
+            bottom = dip2px(getContext(), bottom);
+        }
+        params.gravity = gravity;
+        params.setMargins(left, top, right, bottom);
+        mEditText.setLayoutParams(params);
+    }
+
+    public void setTextVisibility(boolean visible) {
+        mEditText.setVisibility(visible ? VISIBLE : GONE);
+    }
+
+    public void setImageAlpha(int alpha) {
+        mMarkDrawable.setAlpha(alpha);
+        mImageView.setBackground(mMarkDrawable);
+    }
+
+    public static String convertStream2String(InputStream inputStream) {
+        StringBuilder sb = new StringBuilder();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+        String oneLine;
+        try {
+            while ((oneLine = reader.readLine()) != null) {
+                sb.append(oneLine + "\n");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return sb.toString();
+    }
+
+    public RectF getMarkLayoutRect() {
+        return markLayoutRect;
+    }
+
+    public float getFinalMoveY() {
+        return finalMoveY;
+    }
+
+    public float getFinalRotation() {
+        return finalRotation;
+    }
+
+    public float getFinalMoveX() {
+        return finalMoveX;
+    }
+
+    public float getFinalScale() {
+        return lastScale;
+    }
+
+    public String getTextContent() {
+        return text;
+    }
+    public void setTextContent(String text) {
+        this.text = text;
+    }
+
+    public void update() {
+        imageBounds = MasterImage.getImage().getImageBounds();
+        if (!sizeChanged) return;
+        sizeChanged = false;
+        float mw = markLayoutRect.width();
+        Matrix mx = new Matrix();
+        mx.setTranslate(-markLayoutRect.width()/2, -markLayoutRect.height()/2);
+        mx.mapRect(markLayoutRect);
+        mx.reset();
+        oldImageToScreenMatrix.invert(mx);
+        mx.mapRect(markLayoutRect);
+        Bitmap mBitmap = MasterImage.getImage().getHighresImage();
+        oldImageToScreenMatrix = MasterImage.getImage().computeImageToScreen(mBitmap, 0, false);
+        oldImageToScreenMatrix.mapRect(markLayoutRect);
+        mx.reset();
+        mx.setTranslate(markLayoutRect.width()/2,markLayoutRect.height()/2);
+        mx.mapRect(markLayoutRect);
+
+//        Bitmap mBitmap = MasterImage.getImage().getFilteredImage();
+//        scale = scale * GeometryMathUtils.getWatermarkScale(mGeometry, mBitmap.getWidth(),
+//                mBitmap.getHeight(), w, h, oldw, oldh);
+//        mDisplaySegPointsMatrix = GeometryMathUtils.getWatermarkMatrix(mGeometry, mBitmap.getWidth(),
+//                mBitmap.getHeight(), w, h, oldw, oldh);
+//        mDisplaySegPointsMatrix.mapRect(markLayoutRect);
+        scale = scale * markLayoutRect.width() / mw;
+        markLeft = markLayoutRect.left;
+        markTop = markLayoutRect.top;
+        markRight = markLayoutRect.right;
+        markBottom = markLayoutRect.bottom;
+        markLayout.setPivotX(0);
+        markLayout.setPivotY(0);
+        markLayout.setScaleX(scale);
+        markLayout.setScaleY(scale);
+        markLayout.setTranslationX(markLayoutRect.left);
+        markLayout.setTranslationY(markLayoutRect.top);
+        requestLayout();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorBrightnessView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorBrightnessView.java
index b2118e0..b270fa5 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorBrightnessView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorBrightnessView.java
@@ -30,7 +30,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorCompareView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorCompareView.java
index 1599671..c765b4d 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorCompareView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorCompareView.java
@@ -30,7 +30,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
index 0285994..b93434a 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java
@@ -24,7 +24,7 @@
 import android.view.ViewGroup;
 import android.widget.Button;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorHueView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorHueView.java
index 61b3621..e3cafec 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorHueView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorHueView.java
@@ -31,7 +31,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
index 970a2ff..3d3c6a2 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java
@@ -31,7 +31,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
index ff36f5a..478eb9d 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java
@@ -30,7 +30,7 @@
 import android.widget.ImageButton;
 import android.widget.ToggleButton;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.photos.views.GalleryThumbnailView;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
index 92f4ad8..48ffa81 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java
@@ -30,7 +30,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorSVRectView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorSVRectView.java
index 6ebb48b..8a18f87 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorSVRectView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorSVRectView.java
@@ -32,7 +32,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorSaturationView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorSaturationView.java
index a29eee9..e9927d5 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorSaturationView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorSaturationView.java
@@ -30,7 +30,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
index 0ace5d0..0612048 100644
--- a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
+++ b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java
@@ -28,7 +28,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java b/src/com/android/gallery3d/filtershow/controller/ActionSlider.java
index f80a1ca..ce74373 100644
--- a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java
+++ b/src/com/android/gallery3d/filtershow/controller/ActionSlider.java
@@ -22,7 +22,7 @@
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.Editor;
 
 public class ActionSlider extends TitledSlider {
diff --git a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java
index 811b474..d0d0fca 100644
--- a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java
+++ b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java
@@ -20,11 +20,11 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.LinearLayout;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.editors.Editor;
 
 public class BasicSlider implements Control {
@@ -36,14 +36,36 @@
     public void setUp(ViewGroup container, Parameter parameter, Editor editor) {
         container.removeAllViews();
         mEditor = editor;
-        Context context = container.getContext();
+        final Context context = container.getContext();
         mParameter = (ParameterInteger) parameter;
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        LinearLayout lp = (LinearLayout) inflater.inflate(
+        View lp = inflater.inflate(
                 R.layout.filtershow_seekbar, container, true);
         mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar);
         mSeekBar.setVisibility(View.VISIBLE);
+        View saveButton = lp.findViewById(R.id.slider_save);
+        if (saveButton != null) {
+            saveButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) context;
+                    mEditor.finalApplyCalled();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
+        View cancelButton = lp.findViewById(R.id.slider_cancel);
+        if (cancelButton != null) {
+            cancelButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) context;
+                    activity.cancelCurrentFilter();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
         updateUI();
         mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
 
diff --git a/src/com/android/gallery3d/filtershow/controller/ColorChooser.java b/src/com/android/gallery3d/filtershow/controller/ColorChooser.java
index f9f29bc..cfa9260 100644
--- a/src/com/android/gallery3d/filtershow/controller/ColorChooser.java
+++ b/src/com/android/gallery3d/filtershow/controller/ColorChooser.java
@@ -11,7 +11,7 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
 import com.android.gallery3d.filtershow.colorpicker.ColorPickerDialog;
 import com.android.gallery3d.filtershow.editors.Editor;
@@ -68,9 +68,16 @@
             Color.colorToHSV(palette[i], hsvo);
             hsvo[OPACITY_OFFSET] = (0xFF & (palette[i] >> 24)) / (float) 255;
             button.setTag(hsvo);
+
+            String colorString = "(" + Integer.toHexString(palette[i]) + ")";
+            boolean colorSelect = false;
+            if (parameter.getValueString().equals(colorString)) {
+                mSelectedButton = i;
+                colorSelect = true;
+            }
             GradientDrawable sd = ((GradientDrawable) button.getBackground());
             sd.setColor(palette[i]);
-            sd.setStroke(3, (mSelectedButton == i) ? mSelected : mTransparent);
+            sd.setStroke(3, colorSelect? mSelected : mTransparent);
 
             final int buttonNo = i;
             button.setOnClickListener(new View.OnClickListener() {
diff --git a/src/com/android/gallery3d/filtershow/controller/SliderBrightness.java b/src/com/android/gallery3d/filtershow/controller/SliderBrightness.java
index 2929d68..4e704b1 100644
--- a/src/com/android/gallery3d/filtershow/controller/SliderBrightness.java
+++ b/src/com/android/gallery3d/filtershow/controller/SliderBrightness.java
@@ -22,7 +22,7 @@
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorBrightnessView;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
 import com.android.gallery3d.filtershow.colorpicker.ColorOpacityView;
diff --git a/src/com/android/gallery3d/filtershow/controller/SliderHue.java b/src/com/android/gallery3d/filtershow/controller/SliderHue.java
index 1820ce2..dc0042f 100644
--- a/src/com/android/gallery3d/filtershow/controller/SliderHue.java
+++ b/src/com/android/gallery3d/filtershow/controller/SliderHue.java
@@ -31,7 +31,7 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.Log;
 import com.android.gallery3d.filtershow.colorpicker.ColorHueView;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
diff --git a/src/com/android/gallery3d/filtershow/controller/SliderOpacity.java b/src/com/android/gallery3d/filtershow/controller/SliderOpacity.java
index 2a34aad..06ed607 100644
--- a/src/com/android/gallery3d/filtershow/controller/SliderOpacity.java
+++ b/src/com/android/gallery3d/filtershow/controller/SliderOpacity.java
@@ -24,7 +24,7 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
 import com.android.gallery3d.filtershow.colorpicker.ColorOpacityView;
 import com.android.gallery3d.filtershow.editors.Editor;
diff --git a/src/com/android/gallery3d/filtershow/controller/SliderSaturation.java b/src/com/android/gallery3d/filtershow/controller/SliderSaturation.java
index 6f3ae6e..c99de25 100644
--- a/src/com/android/gallery3d/filtershow/controller/SliderSaturation.java
+++ b/src/com/android/gallery3d/filtershow/controller/SliderSaturation.java
@@ -24,7 +24,7 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
 import com.android.gallery3d.filtershow.colorpicker.ColorOpacityView;
 import com.android.gallery3d.filtershow.colorpicker.ColorSaturationView;
diff --git a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java b/src/com/android/gallery3d/filtershow/controller/StyleChooser.java
index f5afec9..674bedd 100644
--- a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java
+++ b/src/com/android/gallery3d/filtershow/controller/StyleChooser.java
@@ -11,7 +11,7 @@
 import android.widget.ImageView.ScaleType;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.pipeline.RenderingRequest;
 import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller;
 import com.android.gallery3d.filtershow.editors.Editor;
@@ -41,11 +41,11 @@
         int n = mParameter.getNumberOfStyles();
         mIconButton.clear();
         Resources res = context.getResources();
-        int dim = res.getDimensionPixelSize(R.dimen.draw_style_icon_dim);
+        int dim = mTopView.getMeasuredWidth() / n;
         LayoutParams lp = new LayoutParams(dim, dim);
         for (int i = 0; i < n; i++) {
             final ImageButton button = new ImageButton(context);
-            button.setScaleType(ScaleType.CENTER_CROP);
+            button.setScaleType(ScaleType.CENTER_INSIDE);
             button.setLayoutParams(lp);
             button.setBackgroundResource(android.R.color.transparent);
             mIconButton.add(button);
diff --git a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java b/src/com/android/gallery3d/filtershow/controller/TitledSlider.java
index f29442b..ed7eaf9 100644
--- a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java
+++ b/src/com/android/gallery3d/filtershow/controller/TitledSlider.java
@@ -25,7 +25,7 @@
 import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.Editor;
 
 public class TitledSlider implements Control {
@@ -88,7 +88,7 @@
     @Override
     public void updateUI() {
         if (mControlName != null && mParameter.getParameterName() != null) {
-            mControlName.setText(mParameter.getParameterName().toUpperCase());
+            mControlName.setText(mParameter.getParameterName());
         }
         if (mControlValue != null) {
             mControlValue.setText(
diff --git a/src/com/android/gallery3d/filtershow/crop/CropActivity.java b/src/com/android/gallery3d/filtershow/crop/CropActivity.java
index 3a78296..afb527d 100644
--- a/src/com/android/gallery3d/filtershow/crop/CropActivity.java
+++ b/src/com/android/gallery3d/filtershow/crop/CropActivity.java
@@ -42,7 +42,7 @@
 import android.view.WindowManager;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.tools.SaveImage;
@@ -83,7 +83,7 @@
      * sure the intent stays below 1MB.We should consider just returning a byte
      * array instead of a Bitmap instance to avoid overhead.
      */
-    public static final int MAX_BMAP_IN_INTENT = 750000;
+    public static final int MAX_BMAP_IN_INTENT = 520000;
 
     // Flags
     private static final int DO_SET_WALLPAPER = 1;
@@ -110,13 +110,22 @@
             actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
             actionBar.setCustomView(R.layout.filtershow_actionbar);
 
-            View mSaveButton = actionBar.getCustomView();
+            View mSaveButton = actionBar.getCustomView().findViewById(
+                    R.id.filtershow_done);
             mSaveButton.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View view) {
                     startFinishOutput();
                 }
             });
+            View mExitButton = actionBar.getCustomView().findViewById(
+                    R.id.filtershow_exit);
+            mExitButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    finish();
+                }
+            });
         }
         if (intent.getData() != null) {
             mSourceUri = intent.getData();
@@ -400,16 +409,8 @@
             mOutputX = outputX;
             mOutputY = outputY;
 
-            if ((flags & DO_EXTRA_OUTPUT) != 0) {
-                if (mOutUri == null) {
-                    Log.w(LOGTAG, "cannot write file, no output URI given");
-                } else {
-                    try {
-                        mOutStream = getContentResolver().openOutputStream(mOutUri);
-                    } catch (FileNotFoundException e) {
-                        Log.w(LOGTAG, "cannot write file: " + mOutUri.toString(), e);
-                    }
-                }
+            if ((flags & DO_EXTRA_OUTPUT) != 0 && mOutUri == null) {
+                Log.w(LOGTAG, "cannot write file, no output URI given");
             }
 
             if ((flags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0) {
@@ -542,7 +543,14 @@
                 // Get output compression format
                 CompressFormat cf =
                         convertExtensionToCompressFormat(getFileExtension(mOutputFormat));
-
+                Utils.closeSilently(mInStream);
+                if (mOutUri != null) {
+                    try {
+                        mOutStream = getContentResolver().openOutputStream(mOutUri);
+                    } catch (FileNotFoundException e) {
+                        Log.w(LOGTAG, "cannot write file: " + mOutUri.toString(), e);
+                    }
+                }
                 // If we only need to output to a URI, compress straight to file
                 if (mFlags == DO_EXTRA_OUTPUT) {
                     if (mOutStream == null
@@ -604,7 +612,7 @@
         @Override
         protected void onPostExecute(Boolean result) {
             Utils.closeSilently(mOutStream);
-            Utils.closeSilently(mInStream);
+            // Utils.closeSilently(mInStream);
             doneBitmapIO(result.booleanValue(), mResultIntent);
         }
 
diff --git a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java b/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
index df0f14f..0430de6 100644
--- a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
+++ b/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.gallery3d.filtershow.crop;
 
+import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Matrix;
@@ -25,13 +26,16 @@
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 
+import org.codeaurora.gallery.R;
+
 public abstract class CropDrawingUtils {
 
-    public static void drawRuleOfThird(Canvas canvas, RectF bounds) {
+    public static void drawRuleOfThird(Canvas canvas, RectF bounds, Context context) {
         Paint p = new Paint();
         p.setStyle(Paint.Style.STROKE);
-        p.setColor(Color.argb(128, 255, 255, 255));
-        p.setStrokeWidth(2);
+        p.setColor(Color.argb(75, 255, 255, 255));
+        p.setStrokeWidth(context.getResources().getDimensionPixelOffset(
+                R.dimen.crop_line_stroke));
         float stepX = bounds.width() / 3.0f;
         float stepY = bounds.height() / 3.0f;
         float x = bounds.left + stepX;
@@ -46,14 +50,43 @@
         }
     }
 
-    public static void drawCropRect(Canvas canvas, RectF bounds) {
+    public static void drawCropRect(Canvas canvas, RectF bounds, Context context) {
         Paint p = new Paint();
         p.setStyle(Paint.Style.STROKE);
         p.setColor(Color.WHITE);
-        p.setStrokeWidth(3);
+        p.setAlpha(75);
+        p.setStrokeWidth(context.getResources().getDimensionPixelOffset(
+                R.dimen.crop_rect_stroke));
         canvas.drawRect(bounds, p);
     }
 
+    public static void drawCorner(Canvas canvas, RectF bounds, Context context) {
+        int strokeWidth = context.getResources().getDimensionPixelOffset(
+                R.dimen.crop_rect_stroke);
+        Paint p = new Paint();
+        p.setStyle(Paint.Style.FILL);
+        p.setColor(Color.WHITE);
+        p.setAntiAlias(true);
+        p.setStrokeWidth(strokeWidth);
+        float cornerLength = context.getResources().getDimensionPixelOffset(
+                R.dimen.crop_corner_length);
+        float rectWidth = bounds.right - bounds.left;
+        float rectHeight = bounds.bottom - bounds.top;
+        float x = 0;
+        float y = 0;
+        for (int i = 0; i < 2; i++) {
+            y = i * rectHeight + bounds.top;
+
+            canvas.drawLine(bounds.left - strokeWidth / 2, y, cornerLength + bounds.left, y, p);
+            canvas.drawLine(bounds.right - cornerLength, y, bounds.right + strokeWidth / 2, y, p);
+        }
+        for (int j = 0; j < 2; j++) {
+            x = j * rectWidth + bounds.left;
+            canvas.drawLine(x, bounds.top, x, bounds.top + cornerLength, p);
+            canvas.drawLine(x, bounds.bottom - cornerLength, x, bounds.bottom, p);
+        }
+    }
+
     public static void drawShade(Canvas canvas, RectF bounds) {
         int w = canvas.getWidth();
         int h = canvas.getHeight();
@@ -174,10 +207,7 @@
             RectF screen, int rotation) {
         RectF rotatedImage = new RectF();
         dst.setRotate(rotation, image.centerX(), image.centerY());
-        if (!dst.mapRect(rotatedImage, image)) {
-            return false; // fails for rotations that are not multiples of 90
-                          // degrees
-        }
+        dst.mapRect(rotatedImage, image);
         boolean rToR = dst.setRectToRect(rotatedImage, screen, Matrix.ScaleToFit.CENTER);
         boolean rot = dst.preRotate(rotation, image.centerX(), image.centerY());
         return rToR && rot;
diff --git a/src/com/android/gallery3d/filtershow/crop/CropMath.java b/src/com/android/gallery3d/filtershow/crop/CropMath.java
index 02c6531..1faf263 100644
--- a/src/com/android/gallery3d/filtershow/crop/CropMath.java
+++ b/src/com/android/gallery3d/filtershow/crop/CropMath.java
@@ -219,9 +219,7 @@
         Matrix m = new Matrix();
         m.setRectToRect(photoBounds, displayBounds, Matrix.ScaleToFit.FILL);
         RectF trueCrop = new RectF(cropBounds);
-        if (!m.mapRect(trueCrop)) {
-            return null;
-        }
+        m.mapRect(trueCrop);
         return trueCrop;
     }
 
diff --git a/src/com/android/gallery3d/filtershow/crop/CropView.java b/src/com/android/gallery3d/filtershow/crop/CropView.java
index bbb7cfd..175fb82 100644
--- a/src/com/android/gallery3d/filtershow/crop/CropView.java
+++ b/src/com/android/gallery3d/filtershow/crop/CropView.java
@@ -32,7 +32,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 
 public class CropView extends View {
@@ -331,14 +331,13 @@
         mScreenImageBounds.set(mImageBounds);
 
         // Draw background shadow
-        if (mDisplayMatrix.mapRect(mScreenImageBounds)) {
-            int margin = (int) mDisplayMatrix.mapRadius(mShadowMargin);
-            mScreenImageBounds.roundOut(mShadowBounds);
-            mShadowBounds.set(mShadowBounds.left - margin, mShadowBounds.top -
-                    margin, mShadowBounds.right + margin, mShadowBounds.bottom + margin);
-            mShadow.setBounds(mShadowBounds);
-            mShadow.draw(canvas);
-        }
+        mDisplayMatrix.mapRect(mScreenImageBounds);
+        int margin = (int) mDisplayMatrix.mapRadius(mShadowMargin);
+        mScreenImageBounds.roundOut(mShadowBounds);
+        mShadowBounds.set(mShadowBounds.left - margin, mShadowBounds.top -
+                margin, mShadowBounds.right + margin, mShadowBounds.bottom + margin);
+        mShadow.setBounds(mShadowBounds);
+        mShadow.draw(canvas);
 
         mPaint.setAntiAlias(true);
         mPaint.setFilterBitmap(true);
@@ -346,32 +345,29 @@
         canvas.drawBitmap(mBitmap, mDisplayMatrix, mPaint);
 
         mCropObj.getInnerBounds(mScreenCropBounds);
+        mDisplayMatrix.mapRect(mScreenCropBounds);
 
-        if (mDisplayMatrix.mapRect(mScreenCropBounds)) {
+        // Draw overlay shadows
+        Paint p = new Paint();
+        p.setColor(mOverlayShadowColor);
+        p.setStyle(Paint.Style.FILL);
+        CropDrawingUtils.drawShadows(canvas, p, mScreenCropBounds, mScreenImageBounds);
 
-            // Draw overlay shadows
-            Paint p = new Paint();
-            p.setColor(mOverlayShadowColor);
-            p.setStyle(Paint.Style.FILL);
-            CropDrawingUtils.drawShadows(canvas, p, mScreenCropBounds, mScreenImageBounds);
-
-            // Draw crop rect and markers
-            CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds);
-            if (!mDoSpot) {
-                CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds);
-            } else {
-                Paint wpPaint = new Paint();
-                wpPaint.setColor(mWPMarkerColor);
-                wpPaint.setStrokeWidth(3);
-                wpPaint.setStyle(Paint.Style.STROKE);
-                wpPaint.setPathEffect(new DashPathEffect(new float[]
-                        {mDashOnLength, mDashOnLength + mDashOffLength}, 0));
-                p.setColor(mOverlayWPShadowColor);
-                CropDrawingUtils.drawWallpaperSelectionFrame(canvas, mScreenCropBounds,
-                        mSpotX, mSpotY, wpPaint, p);
-            }
-            CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize,
-                    mScreenCropBounds, mCropObj.isFixedAspect(), decode(mCropObj.getSelectState(), mRotation));
+        // Draw crop rect and markers
+        CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds, getContext());
+        CropDrawingUtils.drawCorner(canvas, mScreenCropBounds, getContext());
+        if (!mDoSpot) {
+            CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds, getContext());
+        } else {
+            Paint wpPaint = new Paint();
+            wpPaint.setColor(mWPMarkerColor);
+            wpPaint.setStrokeWidth(3);
+            wpPaint.setStyle(Paint.Style.STROKE);
+            wpPaint.setPathEffect(new DashPathEffect(new float[]
+                    {mDashOnLength, mDashOnLength + mDashOffLength}, 0));
+            p.setColor(mOverlayWPShadowColor);
+            CropDrawingUtils.drawWallpaperSelectionFrame(canvas, mScreenCropBounds,
+                    mSpotX, mSpotY, wpPaint, p);
         }
 
     }
diff --git a/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java b/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java
new file mode 100644
index 0000000..9840f9f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/data/FilterPresetDBHelper.java
@@ -0,0 +1,103 @@
+/*
+ * 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.gallery3d.filtershow.data;
+
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+public class FilterPresetDBHelper extends SQLiteOpenHelper {
+
+    public static final int DATABASE_VERSION = 1;
+    public static final String DATABASE_NAME = "filterspreset.db";
+    private static final String SQL_CREATE_TABLE = "CREATE TABLE ";
+
+    public static interface FilterPreset {
+        /** The row uid */
+        public static final String _ID = "_id";
+        /** The table name */
+        public static final String TABLE = "filterspreset";
+        /** The preset name */
+        public static final String PRESET_ID = "preset_id";
+        /** A serialized preset of filters. */
+        public static final String FILTER_PRESET= "preset";
+    }
+
+    private static final String[][] CREATE_FILTER_PRESET = {
+            { FilterPreset._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" },
+            { FilterPreset.PRESET_ID, "TEXT" },
+            { FilterPreset.FILTER_PRESET, "Uri" },
+    };
+
+    public FilterPresetDBHelper(Context context, String name, int version) {
+        super(context, name, null, version);
+    }
+
+    public FilterPresetDBHelper(Context context, String name) {
+        this(context, name, DATABASE_VERSION);
+    }
+
+    public FilterPresetDBHelper(Context context) {
+        this(context, DATABASE_NAME);
+    }
+
+
+    @Override
+    public void onCreate(SQLiteDatabase db) {
+        createTable(db, FilterPreset.TABLE, CREATE_FILTER_PRESET);
+    }
+
+    @Override
+    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        dropTable(db, FilterPreset.TABLE);
+        onCreate(db);
+    }
+
+    protected static void createTable(SQLiteDatabase db, String table, String[][] columns) {
+        StringBuilder create = new StringBuilder(SQL_CREATE_TABLE);
+        create.append(table).append('(');
+        boolean first = true;
+        for (String[] column : columns) {
+            if (!first) {
+                create.append(',');
+            }
+            first = false;
+            for (String val : column) {
+                create.append(val).append(' ');
+            }
+        }
+        create.append(')');
+        db.beginTransaction();
+        try {
+            db.execSQL(create.toString());
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    protected static void dropTable(SQLiteDatabase db, String table) {
+        db.beginTransaction();
+        try {
+            db.execSQL("drop table if exists " + table);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java b/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java
new file mode 100644
index 0000000..f0cbba4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/data/FilterPresetSource.java
@@ -0,0 +1,162 @@
+/*
+ * 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.gallery3d.filtershow.data;
+
+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.util.Log;
+
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper.FilterPreset;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+public class FilterPresetSource {
+    private static final String LOGTAG = "FilterStackSource";
+
+    private SQLiteDatabase database = null;
+    private final FilterPresetDBHelper dbHelper;
+    private Context mContext;
+
+    public FilterPresetSource(Context context) {
+        mContext = context;
+        dbHelper = new FilterPresetDBHelper(context);
+        open();
+    }
+
+    public void open() {
+        try {
+            database = dbHelper.getWritableDatabase();
+        } catch (SQLiteException e) {
+            Log.w(LOGTAG, "could not open database", e);
+        }
+    }
+
+    public void close() {
+        database = null;
+        dbHelper.close();
+    }
+
+    public static class SaveOption {
+        public int _id;
+        public String name;
+        public String Uri;
+    }
+
+    public boolean insertPreset(String presetName, String presetUri) {
+        boolean ret = true;
+        ContentValues val = new ContentValues();
+        val.put(FilterPreset.PRESET_ID, presetName);
+        val.put(FilterPreset.FILTER_PRESET, presetUri);
+        database.beginTransaction();
+        try {
+            ret = (-1 != database.insert(FilterPreset.TABLE, null, val));
+            database.setTransactionSuccessful();
+        } finally {
+            database.endTransaction();
+        }
+        return ret;
+    }
+
+    public void updatePresetName(int id, String presetName) {
+        ContentValues val = new ContentValues();
+        val.put(FilterPreset.PRESET_ID, presetName);
+        database.beginTransaction();
+        try {
+            database.update(FilterPreset.TABLE, val,FilterPreset._ID + " = ?",
+                    new String[] { "" + id});
+            database.setTransactionSuccessful();
+        } finally {
+            database.endTransaction();
+        }
+    }
+
+    public boolean removePreset(int id) {
+        boolean ret = true;
+        database.beginTransaction();
+        try {
+            ret = (0 != database.delete(FilterPreset.TABLE, FilterPreset._ID + " = ?",
+                    new String[] { "" + id }));
+            database.setTransactionSuccessful();
+        } finally {
+            database.endTransaction();
+        }
+        return ret;
+    }
+
+    public ArrayList<SaveOption> getAllUserPresets() {
+        ArrayList<SaveOption> ret = new ArrayList<SaveOption>();
+        Cursor c = null;
+        database.beginTransaction();
+        try {
+            c = database.query(FilterPreset.TABLE,
+                    new String[] { FilterPreset._ID,
+                            FilterPreset.PRESET_ID,
+                            FilterPreset.FILTER_PRESET },
+                    null, null, null, null, null, null);
+            if (c != null) {
+                boolean loopCheck = c.moveToFirst();
+                while (loopCheck) {
+                    String id = (c.isNull(0)) ?  null : c.getString(0);
+                    String name = (c.isNull(1)) ?  null : c.getString(1);
+                    String filterUri = (c.isNull(2)) ? null : c.getString(2);
+                    SaveOption so = new SaveOption();
+                    try {
+                        so._id = Integer.parseInt(id);
+                    } catch (NumberFormatException e) {
+                        e.printStackTrace();
+                    }
+                    so.name = name;
+                    so.Uri = filterUri;
+                    if (!checkUriExist(filterUri)) {
+                        removePreset(so._id);
+                        loopCheck = c.moveToNext();
+                        continue;
+                    }
+                    ret.add(so);
+                    loopCheck = c.moveToNext();
+                }
+            }
+            database.setTransactionSuccessful();
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+            database.endTransaction();
+        }
+        return ret;
+    }
+
+    private boolean checkUriExist(String uriStr) {
+        boolean ret = true;
+        if (uriStr == null) return false;
+        Uri uri = Uri.parse(uriStr);
+        try {
+            InputStream is = mContext.getContentResolver().openInputStream(uri);
+        } catch (FileNotFoundException e) {
+            ret = false;
+            e.printStackTrace();
+            Log.e(LOGTAG, "FileNotFoundException for " + uri, e);
+        }
+        return ret;
+        }
+    }
diff --git a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java b/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java
index 6232a2d..b5f8bb2 100644
--- a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java
+++ b/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java
@@ -3,7 +3,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
diff --git a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
index af694d8..861ed48 100644
--- a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
+++ b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.Control;
 import com.android.gallery3d.filtershow.controller.FilterView;
 import com.android.gallery3d.filtershow.controller.Parameter;
diff --git a/src/com/android/gallery3d/filtershow/editors/Editor.java b/src/com/android/gallery3d/filtershow/editors/Editor.java
index e3eec39..e5d9e48 100644
--- a/src/com/android/gallery3d/filtershow/editors/Editor.java
+++ b/src/com/android/gallery3d/filtershow/editors/Editor.java
@@ -16,10 +16,11 @@
 
 package com.android.gallery3d.filtershow.editors;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 import android.content.Context;
 import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -31,17 +32,16 @@
 import android.widget.PopupMenu;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.Control;
+import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageShow;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
 /**
  * Base class for Editors Must contain a mImageShow and a top level view
  */
@@ -62,6 +62,9 @@
     public static byte SHOW_VALUE_UNDEFINED = -1;
     public static byte SHOW_VALUE_OFF = 0;
     public static byte SHOW_VALUE_INT = 1;
+    private View mActionButton, mEditControl;
+    private TextView mBasicFilterText;
+    private TextView mBasicFilterValue;
 
     public static void hackFixStrings(Menu menu) {
         int count = menu.size();
@@ -72,7 +75,7 @@
     }
 
     public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
-        return effectName.toUpperCase() + " " + parameterValue;
+        return effectName + " " + parameterValue;
     }
 
     protected Editor(int id) {
@@ -91,13 +94,42 @@
         return true;
     }
 
-    public void setUpEditorUI(View actionButton, View editControl,
+    public boolean showsActionBar() {
+        // ActionBar is not need if has seek bar in default.
+        // Subclasses should override if need.
+        return !showsSeekBar();
+    }
+
+    public boolean showsActionBarControls() {
+        return showsActionBar();
+    }
+
+    /*public void setUpEditorUI(View actionButton, View editControl,
                               Button editTitle, Button stateButton) {
         mEditTitle = editTitle;
         mFilterTitle = stateButton;
         mButton = editTitle;
         MasterImage.getImage().resetGeometryImages(false);
         setUtilityPanelUI(actionButton, editControl);
+    }*/
+
+    public void setUpEditorUI(View editControl, Button stateButton) {
+
+        mFilterTitle = stateButton;
+        MasterImage.getImage().resetGeometryImages(false);
+        mEditControl = editControl;
+        setEditPanelUI(editControl);
+    }
+
+    public void setEditorTitle(Button editTitle) {
+        mEditTitle = editTitle;
+        mButton = editTitle;
+    }
+
+    public void setBasicFilterUI(TextView textFilterName,
+            TextView textFilterValue) {
+        mBasicFilterText = textFilterName;
+        mBasicFilterValue = textFilterValue;
     }
 
     public boolean showsPopupIndicator() {
@@ -105,24 +137,23 @@
     }
 
     /**
-     * @param actionButton the would be the area for menu etc
      * @param editControl this is the black area for sliders etc
      */
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-
-        AttributeSet aset;
+    public void setEditPanelUI(View editControl) {
         Context context = editControl.getContext();
         LayoutInflater inflater =
                 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        LinearLayout lp = (LinearLayout) inflater.inflate(
+        View lp = inflater.inflate(
                 R.layout.filtershow_seekbar, (ViewGroup) editControl, true);
         mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar);
         mSeekBar.setOnSeekBarChangeListener(this);
         mSeekBar.setVisibility(View.GONE);
+        editControl.setVisibility(View.GONE);
         if (context.getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_PORTRAIT) {
             if (showsSeekBar()) {
-               mSeekBar.setVisibility(View.VISIBLE);
+                mSeekBar.setVisibility(View.VISIBLE);
+                editControl.setVisibility(View.VISIBLE);
             }
         }
 
@@ -257,6 +288,19 @@
             s = mContext.getString(mLocalRepresentation.getTextId());
         }
         mButton.setText(calculateUserMessage(mContext, s, ""));
+        if (mLocalRepresentation instanceof FilterBasicRepresentation
+                && mBasicFilterText != null) {
+            mBasicFilterText.setText(s);
+            String text = calculateUserMessage(mContext, s, "");
+            String[] split = text.split("[+-]");
+            int length = split.length;
+            if (length == 2)
+                mBasicFilterValue.setText(split[1] != null ? split[1] : "");
+            mBasicFilterText.setVisibility(View.VISIBLE);
+            mBasicFilterValue.setVisibility(View.VISIBLE);
+            mButton.setVisibility(View.INVISIBLE);
+
+        }
     }
 
     /**
@@ -285,7 +329,7 @@
 
     protected void setMenuIcon(boolean on) {
         mEditTitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
-                0, 0, on ? R.drawable.filtershow_menu_marker_rtl : 0, 0);
+                0, 0, on ? R.drawable.spinner_triangle : 0, 0);
     }
 
     protected void createMenu(int[] strId, View button) {
@@ -322,9 +366,23 @@
 
     }
 
+    public void attach() {
+        if (mImageShow != null) {
+            mImageShow.attach();
+        }
+    }
+
     public void detach() {
         if (mImageShow != null) {
             mImageShow.detach();
         }
     }
+
+    public void resume() {
+
+    }
+
+    public void onPrepareOptionsMenu(Menu menu) {
+
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java b/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
index abf0a69..664aa6c 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java
@@ -29,7 +29,7 @@
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
 import android.widget.TextView;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.controller.BasicParameterStyle;
 import com.android.gallery3d.filtershow.controller.BitmapCaller;
@@ -162,19 +162,17 @@
             value = rep.getValue(FilterChanSatRepresentation.MODE_MAGENTA);
             mMagentaBar.setProgress(value + 100);
             mMagentaValue.setText("" + value);
-            String text = mContext.getString(rep.getTextId()).toUpperCase();
-            mFilterTitle.setText(text);
+            super.reflectCurrentFilter();
             updateText();
         }
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
+    public void setEditPanelUI(View editControl) {
         if (useCompact(mContext)) {
-            super.setUtilityPanelUI(actionButton, editControl);
+            super.setEditPanelUI(editControl);
             return;
         }
-        mActionButton = actionButton;
         mEditControl = editControl;
         mEditTitle.setCompoundDrawables(null, null, null, null);
         LinearLayout group = (LinearLayout) editControl;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorColorBorder.java b/src/com/android/gallery3d/filtershow/editors/EditorColorBorder.java
index 98659df..9025285 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorColorBorder.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorColorBorder.java
@@ -17,26 +17,18 @@
 package com.android.gallery3d.filtershow.editors;
 
 import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Color;
-import android.util.Log;
-import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
 import android.widget.SeekBar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
-import com.android.gallery3d.filtershow.controller.BitmapCaller;
 import com.android.gallery3d.filtershow.controller.ColorChooser;
-import com.android.gallery3d.filtershow.controller.FilterView;
 import com.android.gallery3d.filtershow.filters.FilterColorBorderRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.ImageFilterColorBorder;
@@ -176,7 +168,9 @@
             c.setColorSet(mBasColors);
         }
         updateText();
-        mControl.updateUI();
+        if (mControl != null) {
+            mControl.updateUI();
+        }
         mView.invalidate();
     }
 
@@ -185,9 +179,9 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
+    public void setEditPanelUI(View editControl) {
         if (ParametricEditor.useCompact(mContext)) {
-            super.setUtilityPanelUI(actionButton, editControl);
+            super.setEditPanelUI(editControl);
             return;
         }
         mSeekBar = (SeekBar) editControl.findViewById(R.id.primarySeekBar);
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorColorBorderTabletUI.java b/src/com/android/gallery3d/filtershow/editors/EditorColorBorderTabletUI.java
index 9f1a11b..8e7e8b0 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorColorBorderTabletUI.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorColorBorderTabletUI.java
@@ -28,7 +28,7 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorCompareView;
 import com.android.gallery3d.filtershow.colorpicker.ColorHueView;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java b/src/com/android/gallery3d/filtershow/editors/EditorCrop.java
index 6b19d3c..e84be4b 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorCrop.java
@@ -27,7 +27,7 @@
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
@@ -78,7 +78,6 @@
             mImageCrop = new ImageCrop(context);
         }
         mView = mImageShow = mImageCrop;
-        mImageCrop.setEditor(this);
     }
 
     @Override
@@ -114,7 +113,7 @@
         });
     }
 
-    private void changeCropAspect(int itemId) {
+    public void changeCropAspect(int itemId) {
         AspectInfo info = sAspects.get(itemId);
         if (info == null) {
             throw new IllegalArgumentException("Invalid resource ID: " + itemId);
@@ -145,8 +144,8 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-        super.setUtilityPanelUI(actionButton,editControl);
+    public void setEditPanelUI(View editControl) {
+        super.setEditPanelUI(editControl);
         setMenuIcon(true);
     }
 
@@ -156,6 +155,11 @@
     }
 
     @Override
+    public boolean showsActionBar() {
+        return false;
+    }
+
+    @Override
     public int getTextId() {
         return R.string.crop;
     }
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
index 35ac359..e305f7a 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java
@@ -20,7 +20,7 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageCurves;
@@ -61,8 +61,8 @@
         }
     }
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-        super.setUtilityPanelUI(actionButton,editControl);
+    public void setEditPanelUI(View editControl) {
+        super.setEditPanelUI(editControl);
         setMenuIcon(true);
     }
 
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
index 58bde12..5298cab 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java
@@ -37,7 +37,7 @@
 import android.widget.PopupMenu;
 import android.widget.SeekBar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.colorpicker.ColorHueView;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
@@ -61,11 +61,11 @@
     private static final int MODE_STYLE = FilterDrawRepresentation.PARAM_STYLE;
     private static final int MODE_COLOR = FilterDrawRepresentation.PARAM_COLOR;
     int[] brushIcons = {
-            R.drawable.brush_flat,
-            R.drawable.brush_round,
-            R.drawable.brush_gauss,
-            R.drawable.brush_marker,
-            R.drawable.brush_spatter
+            R.drawable.square,
+            R.drawable.round,
+            R.drawable.feather,
+            R.drawable.rectangle,
+            R.drawable.random
     };
 
     int[] mBasColors = {
@@ -241,9 +241,9 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
+    public void setEditPanelUI(View editControl) {
         if (ParametricEditor.useCompact(mContext)) {
-            super.setUtilityPanelUI(actionButton, editControl);
+            super.setEditPanelUI(editControl);
             return;
         }
 
@@ -257,7 +257,7 @@
                 R.layout.filtershow_draw_ui, (ViewGroup) editControl, true);
 
         mTabletUI = new EditorDrawTabletUI(this, mContext, lp);
-        mDrawString = mContext.getResources().getString(R.string.imageDraw).toUpperCase();
+        mDrawString = mContext.getResources().getString(R.string.imageDraw);
         setMenuIcon(true);
 
     }
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDrawTabletUI.java b/src/com/android/gallery3d/filtershow/editors/EditorDrawTabletUI.java
index 83d89c9..ea01e10 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorDrawTabletUI.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDrawTabletUI.java
@@ -31,7 +31,7 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.colorpicker.ColorCompareView;
 import com.android.gallery3d.filtershow.colorpicker.ColorHueView;
 import com.android.gallery3d.filtershow.colorpicker.ColorListener;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
new file mode 100644
index 0000000..ec6c8ae
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamFusion.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageFusion;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
+
+import org.codeaurora.gallery.R;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class EditorDualCamFusion extends Editor {
+    public static final String TAG = EditorDualCamFusion.class.getSimpleName();
+    public static final int ID = R.id.editorDualCamFusion;
+
+    protected ImageFusion mImageFusion;
+    private Uri mUnderlayUri = Uri.EMPTY;
+
+    public EditorDualCamFusion() {
+        super(ID);
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return true;
+    }
+
+    @Override
+    public boolean showsActionBarControls() {
+        return false;
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
+    }
+
+    public boolean useUtilityPanel() {
+        return true;
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        if (mImageFusion == null) {
+            mImageFusion = new ImageFusion(context);
+        }
+        mView = mImageShow = mImageFusion;
+        mImageFusion.setEditor(this);
+    }
+
+    @Override
+    public void setEditPanelUI(View editControl) {
+        ViewGroup controlContainer = (ViewGroup) editControl;
+        controlContainer.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        View controls = inflater.inflate(R.layout.filtershow_seekbar, controlContainer);
+        View seekbar = controls.findViewById(R.id.primarySeekBar);
+        seekbar.setVisibility(View.GONE);
+        View saveButton = controls.findViewById(R.id.slider_save);
+        if (saveButton != null) {
+            saveButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) mContext;
+                    finalApplyCalled();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
+        View cancelButton = controls.findViewById(R.id.slider_cancel);
+        if (cancelButton != null) {
+            cancelButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) mContext;
+                    activity.cancelCurrentFilter();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
+    }
+
+    @Override
+    public void openUtilityPanel(final LinearLayout accessoryViewList) {
+        accessoryViewList.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.filtershow_actionbar_dualcam_fusion, accessoryViewList);
+
+        View pickUnderlayBtn = accessoryViewList.findViewById(R.id.pick_underlay);
+        pickUnderlayBtn.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+            }
+        });
+
+        // Look for previous underlay
+        String fusionUnderlay = GalleryUtils.getStringPref(mContext,
+                mContext.getString(R.string.pref_dualcam_fusion_underlay_key), null);
+        Uri fusionUri = Uri.EMPTY;
+
+        if (fusionUnderlay != null) {
+            fusionUri = Uri.parse(fusionUnderlay);
+            if (!uriExists(mContext, fusionUri))
+                fusionUri = Uri.EMPTY;
+        }
+
+        setUnderlayImageUri(fusionUri);
+    }
+
+    @Override
+    public void resume() {
+        if (mUnderlayUri.equals(Uri.EMPTY)) {
+            // No underlay set.
+            boolean skipIntro = GalleryUtils.getBooleanPref(mContext,
+                    mContext.getString(R.string.pref_dualcam_fusion_intro_show_key), false);
+            if (!skipIntro) {
+                FragmentManager fm = ((FilterShowActivity) mContext).getSupportFragmentManager();
+                DoNotShowAgainDialog dialog =
+                        (DoNotShowAgainDialog) fm.findFragmentByTag("dualcam_fusion_intro");
+                if (dialog == null) {
+                    dialog = new DoNotShowAgainDialog(
+                            R.string.fusion_pick_background, R.string.dualcam_fusion_intro,
+                            R.string.pref_dualcam_fusion_intro_show_key);
+                    dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            FilterShowActivity activity = (FilterShowActivity) mContext;
+                            activity.cancelCurrentFilter();
+                            activity.leaveSeekBarPanel();
+                        }
+                    });
+                    dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int id) {
+                            MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+                        }
+                    });
+                    dialog.setCancelable(true);
+                    dialog.show(fm, "dualcam_fusion_intro");
+                } else if (dialog.isDetached()) {
+                    FragmentTransaction ft = fm.beginTransaction();
+                    ft.attach(dialog);
+                    ft.commit();
+                } else if (dialog.isHidden()) {
+                    FragmentTransaction ft = fm.beginTransaction();
+                    ft.show(dialog);
+                    ft.commit();
+                }
+            }
+        }
+    }
+
+    public void setUnderlayImageUri(Uri uri) {
+        mUnderlayUri = uri;
+        FilterRepresentation filter = getLocalRepresentation();
+        if (filter instanceof FilterDualCamFusionRepresentation) {
+            mImageFusion.setUnderlay(uri);
+            commitLocalRepresentation();
+
+            // save fusion underlay uri
+            GalleryUtils.setStringPref(mContext,
+                    mContext.getString(R.string.pref_dualcam_fusion_underlay_key),
+                    (uri != null) ? uri.toString() : null);
+        }
+    }
+
+    @Override
+    public void reflectCurrentFilter() {
+        super.reflectCurrentFilter();
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null && rep instanceof FilterDualCamFusionRepresentation) {
+            FilterDualCamFusionRepresentation dualRep = (FilterDualCamFusionRepresentation) rep;
+            mImageFusion.setRepresentation(dualRep);
+        }
+    }
+
+    private boolean uriExists(Context context, Uri uri) {
+        try {
+            InputStream stream = context.getContentResolver().openInputStream(uri);
+            stream.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return false;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java
new file mode 100644
index 0000000..f721117
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamSketch.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageDualCamera;
+
+public class EditorDualCamSketch extends ImageOnlyEditor {
+    public static final int ID = R.id.editorDualCamSketch;
+    private static final String LOGTAG = "EditorDualCamSketch";
+    private ImageDualCamera mImageDualCam;
+
+    public EditorDualCamSketch() {
+        super(ID);
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        if (mImageDualCam == null) {
+            mImageDualCam = new ImageDualCamera(context);
+        }
+        mView = mImageShow = mImageDualCam;
+        mImageDualCam.setEditor(this);
+    }
+
+    @Override
+    public void reflectCurrentFilter() {
+        super.reflectCurrentFilter();
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null && rep instanceof FilterDualCamBasicRepresentation) {
+            FilterDualCamBasicRepresentation dualRep = (FilterDualCamBasicRepresentation) rep;
+            mImageDualCam.setRepresentation(dualRep);
+        }
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java b/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java
new file mode 100644
index 0000000..f4e155e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorDualCamera.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageDualCamera;
+
+public class EditorDualCamera extends BasicEditor {
+    public static final int ID = R.id.editorDualCam;
+    private static final String LOGTAG = "EditorDualCamera";
+    private ImageDualCamera mImageDualCam;
+
+    public EditorDualCamera() {
+        super(ID, R.layout.filtershow_dualcamera_editor, R.id.editorDualCam);
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mImageDualCam = (ImageDualCamera) mImageShow;
+        mImageDualCam.setEditor(this);
+    }
+
+    @Override
+    public void reflectCurrentFilter() {
+        super.reflectCurrentFilter();
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null && rep instanceof FilterDualCamBasicRepresentation) {
+            FilterDualCamBasicRepresentation dualRep = (FilterDualCamBasicRepresentation) rep;
+            mImageDualCam.setRepresentation(dualRep);
+        }
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        FilterRepresentation r = getLocalRepresentation();
+        if (r != null && r instanceof FilterBasicRepresentation) {
+            FilterBasicRepresentation repr = (FilterBasicRepresentation) r;
+            return repr.getMaximum() != repr.getMinimum();
+        }
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java
index 0591216..2500011 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java
@@ -30,7 +30,7 @@
 import android.widget.TextView;
 import android.widget.ToggleButton;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.controller.Control;
 import com.android.gallery3d.filtershow.controller.FilterView;
@@ -51,8 +51,8 @@
     private static final int MODE_BRIGHTNESS = FilterGradRepresentation.PARAM_BRIGHTNESS;
     private static final int MODE_SATURATION = FilterGradRepresentation.PARAM_SATURATION;
     private static final int MODE_CONTRAST = FilterGradRepresentation.PARAM_CONTRAST;
-    private static final int ADD_ICON = R.drawable.ic_grad_add;
-    private static final int DEL_ICON = R.drawable.ic_grad_del;
+    private static final int ADD_ICON = R.drawable.addspot;
+    private static final int DEL_ICON = R.drawable.delete;
     private int mSliderMode = MODE_BRIGHTNESS;
     ImageGrad mImageGrad;
     ParamAdapter []mAdapters = new ParamAdapter[3];
@@ -140,9 +140,9 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
+    public void setEditPanelUI(View editControl) {
         if (ParametricEditor.useCompact(mContext)) {
-            super.setUtilityPanelUI(actionButton, editControl);
+            super.setEditPanelUI(editControl);
             return;
         }
         mSeekBar = (SeekBar) editControl.findViewById(R.id.primarySeekBar);
@@ -215,7 +215,7 @@
             if (mSliderMode != mMode) {
                 mSliderMode = mMode;
                 mEffectName = mContext.getResources().getString(getModeNameid(mMode));
-                mEffectName = mEffectName.toUpperCase();
+//                mEffectName = mEffectName.toUpperCase();
             }
             mTextView.setText(Integer.toString(value));
             mView.invalidate();
@@ -311,7 +311,7 @@
             return mEffectName;
         }
         int val = rep.getParameter(mSliderMode);
-        return mEffectName.toUpperCase() + ((val > 0) ? " +" : " ") + val;
+        return mEffectName + ((val > 0) ? " +" : " ") + val;
     }
 
     private FilterGradRepresentation getGradRepresentation() {
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorMakeup.java b/src/com/android/gallery3d/filtershow/editors/EditorMakeup.java
new file mode 100644
index 0000000..50377c1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorMakeup.java
@@ -0,0 +1,44 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.view.View;
+import android.widget.SeekBar;
+
+import org.codeaurora.gallery.R;
+
+public class EditorMakeup extends BasicEditor {
+    public static int ID = R.id.editorMakeup;
+    private final String LOGTAG = "EditorMakeup";
+
+    public EditorMakeup() {
+        super(ID, R.layout.filtershow_default_editor, R.id.basicEditor);
+    }
+
+    @Override
+    public void setEditPanelUI(View editControl) {
+        super.setEditPanelUI(editControl);
+        mSeekBar = (SeekBar) editControl.findViewById(R.id.primarySeekBar);
+        if (mSeekBar != null) {
+            mSeekBar.setVisibility(View.INVISIBLE);
+        }
+    }
+
+
+
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java b/src/com/android/gallery3d/filtershow/editors/EditorMirror.java
index d6d9ee7..4be00d6 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorMirror.java
@@ -24,7 +24,7 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageMirror;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
index 51e01d0..a604e02 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java
@@ -20,13 +20,17 @@
 import android.os.Bundle;
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentTransaction;
+import android.util.Log;
 import android.view.LayoutInflater;
+import android.view.Menu;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
-import com.android.gallery3d.R;
+import android.widget.TextView;
+
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.history.HistoryManager;
 import com.android.gallery3d.filtershow.category.MainPanel;
@@ -36,6 +40,7 @@
 public class EditorPanel extends Fragment {
 
     private static final String LOGTAG = "EditorPanel";
+    public static final String FRAGMENT_TAG = "EditorPanel";
 
     private LinearLayout mMainView;
     private Editor mEditor;
@@ -50,6 +55,11 @@
         super.onAttach(activity);
         FilterShowActivity filterShowActivity = (FilterShowActivity) activity;
         mEditor = filterShowActivity.getEditor(mEditorID);
+        if (mEditor != null) {
+            mEditor.attach();
+        }
+        Log.d(LOGTAG, "EditorPanel.onAttach(): mEditorID is " + mEditorID +
+                ", mEditor is " + mEditor);
     }
 
     public void cancelCurrentFilter() {
@@ -74,44 +84,27 @@
             return mMainView;
         }
         mMainView = (LinearLayout) inflater.inflate(R.layout.filtershow_editor_panel, null);
-
-        View actionControl = mMainView.findViewById(R.id.panelAccessoryViewList);
+        //TextView mFilterText = (TextView) mMainView.findViewById(R.id.tvFilterName);
         View editControl = mMainView.findViewById(R.id.controlArea);
-        ImageButton cancelButton = (ImageButton) mMainView.findViewById(R.id.cancelFilter);
-        ImageButton applyButton = (ImageButton) mMainView.findViewById(R.id.applyFilter);
-        Button editTitle = (Button) mMainView.findViewById(R.id.applyEffect);
-        cancelButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                cancelCurrentFilter();
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                activity.backToMain();
-            }
-        });
-
         Button toggleState = (Button) mMainView.findViewById(R.id.toggle_state);
         mEditor = activity.getEditor(mEditorID);
         if (mEditor != null) {
-            mEditor.setUpEditorUI(actionControl, editControl, editTitle, toggleState);
+            mEditor.setUpEditorUI(editControl, toggleState);
             mEditor.reflectCurrentFilter();
-            if (mEditor.useUtilityPanel()) {
-                mEditor.openUtilityPanel((LinearLayout) actionControl);
-            }
         }
-        applyButton.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                mEditor.finalApplyCalled();
-                activity.backToMain();
-            }
-        });
-
         showImageStatePanel(activity.isShowingImageStatePanel());
         return mMainView;
     }
 
     @Override
+    public void onResume() {
+        if (mEditor != null) {
+            mEditor.resume();
+        }
+        super.onResume();
+    }
+
+    @Override
     public void onDetach() {
         if (mEditor != null) {
             mEditor.detach();
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
index b0e88dd..df381a5 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.widget.FrameLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageRedEye;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java b/src/com/android/gallery3d/filtershow/editors/EditorRotate.java
index 9452bf0..a12a41d 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorRotate.java
@@ -24,7 +24,7 @@
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageRotate;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java b/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java
index ff84ba8..5f33739 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java
@@ -20,7 +20,7 @@
 import android.util.Log;
 import android.widget.FrameLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageStraighten;
@@ -41,7 +41,7 @@
     public String calculateUserMessage(Context context, String effectName, Object parameterValue) {
         String apply = context.getString(R.string.apply_effect);
         apply += " " + effectName;
-        return apply.toUpperCase();
+        return apply;
     }
 
     @Override
@@ -97,6 +97,11 @@
     }
 
     @Override
+    public boolean showsActionBar() {
+        return false;
+    }
+
+    @Override
     public boolean showsPopupIndicator() {
         return false;
     }
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
index 9376fbe..d55f1d3 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.widget.FrameLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation;
 import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitBasic.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitBasic.java
new file mode 100644
index 0000000..a09e216
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitBasic.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.LinearLayout;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+
+public class EditorTruePortraitBasic extends BasicEditor  {
+    private static final String LOGTAG = "EditorTruePortraitBasic";
+    public static final int ID = R.id.editorTruePortraitBasic;
+
+    public EditorTruePortraitBasic() {
+        super(ID);
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return true;
+    }
+
+    @Override
+    public boolean showsActionBarControls() {
+        return false;
+    }
+
+    @Override
+    public void openUtilityPanel(LinearLayout accessoryViewList) {
+        accessoryViewList.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.filtershow_actionbar_trueportrait, accessoryViewList);
+
+        View editMask = accessoryViewList.findViewById(R.id.editMask);
+        editMask.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                FilterRepresentation representation = new FilterRepresentation("");
+                representation.setEditorId(EditorTruePortraitMask.ID);
+                ((FilterShowActivity)mContext).loadEditorPanel(representation);
+            }
+        });
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
new file mode 100644
index 0000000..20ff331
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitFusion.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTruePortraitFusionRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageTruePortraitFusion;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.ui.DoNotShowAgainDialog;
+import com.android.gallery3d.util.GalleryUtils;
+
+public class EditorTruePortraitFusion extends Editor {
+    public static final String TAG = "EditorTruePortraitFusion";
+    public static final int ID = R.id.editorTruePortraitFusion;
+
+    protected ImageTruePortraitFusion mImageFusion;
+    private Uri mUnderlayUri = Uri.EMPTY;
+    private boolean pickDialogHasShown = false;
+
+    public EditorTruePortraitFusion() {
+        super(ID);
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return true;
+    }
+
+    @Override
+    public boolean showsActionBarControls() {
+        return false;
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        if (mImageFusion == null) {
+            mImageFusion = new ImageTruePortraitFusion(context);
+        }
+        mView = mImageShow = mImageFusion;
+        mImageFusion.setEditor(this);
+    }
+
+    @Override
+    public void setEditPanelUI(View editControl) {
+        ViewGroup controlContainer = (ViewGroup)editControl;
+        controlContainer.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        View controls = inflater.inflate(R.layout.filtershow_seekbar, controlContainer);
+        View seekbar = controls.findViewById(R.id.primarySeekBar);
+        seekbar.setVisibility(View.GONE);
+        View saveButton = controls.findViewById(R.id.slider_save);
+        if (saveButton != null) {
+            saveButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) mContext;
+                    finalApplyCalled();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
+        View cancelButton = controls.findViewById(R.id.slider_cancel);
+        if (cancelButton != null) {
+            cancelButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    FilterShowActivity activity = (FilterShowActivity) mContext;
+                    activity.cancelCurrentFilter();
+                    activity.leaveSeekBarPanel();
+                }
+            });
+        }
+    }
+
+    @Override
+    public void openUtilityPanel(final LinearLayout accessoryViewList) {
+        accessoryViewList.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.filtershow_actionbar_trueportrait_fusion, accessoryViewList);
+
+        View pickUnderlayBtn = accessoryViewList.findViewById(R.id.pick_underlay);
+        pickUnderlayBtn.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+            }
+        });
+
+        View editMaskBtn = accessoryViewList.findViewById(R.id.editMask);
+        editMaskBtn.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                FilterRepresentation representation = new FilterRepresentation("");
+                representation.setEditorId(EditorTruePortraitMask.ID);
+                ((FilterShowActivity)mContext).loadEditorPanel(representation);
+            }
+        });
+
+        // Look for previous underlay
+        String fusionUnderlay = GalleryUtils.getStringPref(mContext,
+                mContext.getString(R.string.pref_trueportrait_fusion_underlay_key), null);
+        Uri fusionUri = Uri.EMPTY;
+
+        if(fusionUnderlay != null) {
+            fusionUri = Uri.parse(fusionUnderlay);
+            if(!uriExists(mContext, fusionUri))
+                fusionUri = Uri.EMPTY;
+        }
+
+        pickDialogHasShown = false;
+        setUnderlayImageUri(fusionUri);
+    }
+
+    @Override
+    public void resume() {
+        if(mUnderlayUri.equals(Uri.EMPTY) && !pickDialogHasShown) {
+            // No underlay set.
+            boolean skipIntro = GalleryUtils.getBooleanPref(mContext,
+                    mContext.getString(R.string.pref_trueportrait_fusion_intro_show_key), false);
+            if(!skipIntro) {
+                FragmentManager fm = ((FilterShowActivity)mContext).getSupportFragmentManager();
+                DoNotShowAgainDialog dialog =
+                        (DoNotShowAgainDialog) fm.findFragmentByTag("trueportrait_fusion_intro");
+                if(dialog == null) {
+                    dialog = new DoNotShowAgainDialog(
+                            R.string.fusion_pick_background, R.string.trueportrait_fusion_intro,
+                            R.string.pref_trueportrait_fusion_intro_show_key);
+                    dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            FilterShowActivity activity = (FilterShowActivity) mContext;
+                            activity.cancelCurrentFilter();
+                            activity.leaveSeekBarPanel();
+                        }
+                    });
+                    dialog.setOnOkButtonClickListener(new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int id) {
+                            pickDialogHasShown = true;
+                            MasterImage.getImage().getActivity().pickImage(FilterShowActivity.SELECT_FUSION_UNDERLAY);
+                        }
+                    });
+                    dialog.setCancelable(true);
+                    dialog.show(fm, "trueportrait_fusion_intro");
+                } else if (dialog.isDetached()) {
+                    FragmentTransaction ft = fm.beginTransaction();
+                    ft.attach(dialog);
+                    ft.commit();
+                } else if (dialog.isHidden()) {
+                    FragmentTransaction ft = fm.beginTransaction();
+                    ft.show(dialog);
+                    ft.commit();
+                }
+            }
+        }
+    }
+
+    public void setUnderlayImageUri(Uri uri) {
+        mUnderlayUri = uri;
+        FilterRepresentation filter = getLocalRepresentation();
+        if(filter instanceof FilterTruePortraitFusionRepresentation) {
+            mImageFusion.setUnderlay(uri);
+            commitLocalRepresentation();
+
+            // save fusion underlay uri
+            GalleryUtils.setStringPref(mContext,
+                    mContext.getString(R.string.pref_trueportrait_fusion_underlay_key),
+                    (uri != null)?uri.toString():null);
+        }
+    }
+
+    @Override
+    public void reflectCurrentFilter() {
+        super.reflectCurrentFilter();
+        FilterRepresentation rep = getLocalRepresentation();
+        if (rep != null && rep instanceof FilterTruePortraitFusionRepresentation) {
+            FilterTruePortraitFusionRepresentation fusionRep = (FilterTruePortraitFusionRepresentation) rep;
+            mImageFusion.setRepresentation(fusionRep);
+        }
+    }
+
+    private boolean uriExists(Context context, Uri uri) {
+        try {
+            InputStream stream = context.getContentResolver().openInputStream(uri);
+            stream.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            return false;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitImageOnly.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitImageOnly.java
new file mode 100644
index 0000000..781b2e4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitImageOnly.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+
+public class EditorTruePortraitImageOnly extends Editor  {
+    private static final String LOGTAG = "EditorTruePortraitImageOnly";
+    public static final int ID = R.id.editorTruePortraitImageOnly;
+
+    public EditorTruePortraitImageOnly() {
+        super(ID);
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mView = mImageShow = new ImageShow(context);
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+
+    @Override
+    public boolean showsActionBarControls() {
+        return false;
+    }
+
+    @Override
+    public void openUtilityPanel(LinearLayout accessoryViewList) {
+        accessoryViewList.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.filtershow_actionbar_trueportrait, accessoryViewList);
+
+        View editMask = accessoryViewList.findViewById(R.id.editMask);
+        editMask.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                FilterRepresentation representation = new FilterRepresentation("");
+                representation.setEditorId(EditorTruePortraitMask.ID);
+                ((FilterShowActivity)mContext).loadEditorPanel(representation);
+            }
+        });
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitMask.java b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitMask.java
new file mode 100644
index 0000000..c4a0f94
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/EditorTruePortraitMask.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+
+import android.content.Context;
+import androidx.fragment.app.FragmentManager;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.CompoundButton;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.ToggleButton;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.imageshow.ImageTruePortraitMask;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.ui.AlertMsgDialog;
+
+public class EditorTruePortraitMask extends Editor  {
+    private static final String LOGTAG = "EditorTruePortraitMask";
+    public static final int ID = R.id.editorTruePortraitMask;
+
+    private AlertMsgDialog mHelpDialog;
+    private ImageTruePortraitMask mTruePortraitImage;
+    private ToggleButton mForeground;
+    private ToggleButton mBackground;
+    private ImageButton mExitButton;
+    private ImageButton mApplyButton;
+    private View mMaskUndoButton;
+    private View mBrushSizeButton;
+    private View[] mBrushSizes = new View[3];
+    private int mBrushIndex = 0;
+
+    private static final int[] BRUSH_SIZES = {
+        10, 30, 50
+    };
+
+    private OnClickListener mDoneClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View view) {
+            if(view.getId() == R.id.done) {
+                finalApplyCalled();
+            }
+            FilterShowActivity activity = (FilterShowActivity) mContext;
+            activity.backToMain();
+            activity.setActionBar();
+        }
+    };
+
+    public EditorTruePortraitMask() {
+        super(ID);
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        unpack(R.id.truePortraitMaskEditor, R.layout.filtershow_trueportrait_mask_editor);
+        mTruePortraitImage = (ImageTruePortraitMask)mImageShow;
+        mTruePortraitImage.setEditor(this);
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+
+    @Override
+    public boolean showsActionBarControls() {
+        return false;
+    }
+
+    @Override
+    public void openUtilityPanel(LinearLayout accessoryViewList) {
+        accessoryViewList.removeAllViews();
+
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService
+                (Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.filtershow_actionbar_trueportrait_mask, accessoryViewList);
+
+        mMaskUndoButton = accessoryViewList.findViewById(R.id.maskUndo);
+        mMaskUndoButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                mTruePortraitImage.undoLastEdit();
+            }
+        });
+        refreshUndoButton();
+
+        View maskHelp = accessoryViewList.findViewById(R.id.maskHelp);
+        maskHelp.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if(mHelpDialog == null)
+                    mHelpDialog = new AlertMsgDialog(R.string.help, R.string.trueportrait_edit_help);
+
+                FragmentManager fm = ((FilterShowActivity)mContext).getSupportFragmentManager();
+                mHelpDialog.show(fm, "tp_edit_help");
+            }
+        });
+
+        mForeground = (ToggleButton)accessoryViewList.findViewById(R.id.maskForeground);
+        mForeground.setChecked(true);
+        mForeground.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                if(mBackground.isChecked() == isChecked)
+                    mBackground.toggle();
+                mTruePortraitImage.invalidate();
+                showToast();
+            }
+        });
+
+        mBackground = (ToggleButton)accessoryViewList.findViewById(R.id.maskBackground);
+        mBackground.setChecked(false);
+        mBackground.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                if(mForeground.isChecked() == isChecked)
+                    mForeground.toggle();
+            }
+        });
+    }
+
+    @Override
+    public void setUpEditorUI(View editControl, Button stateButton) {
+        mExitButton = (ImageButton) editControl.findViewById(R.id.cancel);
+        mApplyButton = (ImageButton) editControl.findViewById(R.id.done);
+        mExitButton.setOnClickListener(mDoneClickListener);
+        mApplyButton.setOnClickListener(mDoneClickListener);
+
+        mBrushSizeButton = editControl.findViewById(R.id.brush_size);
+        mBrushSizeButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                cycleBrushSize();
+            }
+        });
+
+        mBrushSizes[0] = editControl.findViewById(R.id.brush_size_sm);
+        mBrushSizes[0].setSelected(false);
+        mBrushSizes[1] = editControl.findViewById(R.id.brush_size_med);
+        mBrushSizes[1].setSelected(false);
+        mBrushSizes[2] = editControl.findViewById(R.id.brush_size_large);
+        mBrushSizes[2].setSelected(false);
+
+        mBrushSizes[mBrushIndex].setSelected(true);
+    }
+
+    @Override
+    public void onPrepareOptionsMenu(Menu menu) {
+        menu.clear();
+    }
+
+    @Override
+    public void finalApplyCalled() {
+        mTruePortraitImage.applyMaskUpdates();
+        MasterImage.getImage().invalidateFiltersOnly();
+    }
+
+    private void showToast() {
+        Toast toast;
+        if(isBackgroundMode()) {
+            toast = Toast.makeText(mContext, R.string.trueportrait_edit_background_toast, Toast.LENGTH_LONG);
+        } else {
+            toast = Toast.makeText(mContext, R.string.trueportrait_edit_foreground_toast, Toast.LENGTH_LONG);
+        }
+
+        toast.show();
+    }
+
+    public void refreshUndoButton() {
+        mMaskUndoButton.setEnabled(mTruePortraitImage.canUndoEdit());
+    }
+
+    public boolean isBackgroundMode() {
+        return mBackground.isChecked();
+    }
+
+    public int cycleBrushSize() {
+        mBrushSizes[mBrushIndex].setSelected(false);
+        mBrushIndex = (mBrushIndex+1)%BRUSH_SIZES.length;
+        mBrushSizes[mBrushIndex].setSelected(true);
+        return getBrushSize();
+    }
+
+    public int getBrushSize() {
+        return BRUSH_SIZES[mBrushIndex];
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
index 630a1a9..e3dd7ff 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java
@@ -28,7 +28,7 @@
 import android.widget.SeekBar;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
 import com.android.gallery3d.filtershow.controller.Parameter;
@@ -128,8 +128,7 @@
             }
 
             mImageVignette.setRepresentation(rep);
-            String text = mContext.getString(rep.getTextId()).toUpperCase();
-            mFilterTitle.setText(text);
+            super.reflectCurrentFilter();
             updateText();
         }
     }
@@ -188,12 +187,11 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
+    public void setEditPanelUI(View editControl) {
         if (useCompact(mContext)) {
-            super.setUtilityPanelUI(actionButton, editControl);
+            super.setEditPanelUI(editControl);
             return;
         }
-        mActionButton = actionButton;
         mEditControl = editControl;
         mEditTitle.setCompoundDrawables(null, null, null, null);
         LinearLayout group = (LinearLayout) editControl;
diff --git a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java b/src/com/android/gallery3d/filtershow/editors/EditorZoom.java
index ea8e3d1..2d1d250 100644
--- a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java
+++ b/src/com/android/gallery3d/filtershow/editors/EditorZoom.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.editors;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class EditorZoom extends BasicEditor {
     public static final int ID = R.id.imageZoom;
diff --git a/src/com/android/gallery3d/filtershow/editors/HazeBusterEditor.java b/src/com/android/gallery3d/filtershow/editors/HazeBusterEditor.java
new file mode 100644
index 0000000..8b7f4b8
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/HazeBusterEditor.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.ImageTrueScanner;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+public class HazeBusterEditor extends Editor {
+    public final static int ID = R.id.hazeBusterEditor;
+    private final String LOGTAG = "HazeBusterEditor";
+
+    public HazeBusterEditor() {
+        super(ID);
+    }
+
+    protected HazeBusterEditor(int id) {
+        super(id);
+    }
+
+    public boolean useUtilityPanel() {
+        return false;
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mView = mImageShow = new ImageShow(context);
+    }
+
+    @Override
+    public void finalApplyCalled() {
+        super.finalApplyCalled();
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return false;
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
index d4e66ed..e48e7a6 100644
--- a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
+++ b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.widget.FrameLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.imageshow.ImageShow;
 
 /**
@@ -37,6 +37,11 @@
         super(id);
     }
 
+    @Override
+    public boolean showsActionBar() {
+        return true;
+    }
+
     public boolean useUtilityPanel() {
         return false;
     }
diff --git a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java b/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java
index c168657..5f4c51c 100644
--- a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java
+++ b/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java
@@ -28,7 +28,7 @@
 import android.widget.LinearLayout;
 import android.widget.SeekBar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.ActionSlider;
 import com.android.gallery3d.filtershow.controller.BasicSlider;
 import com.android.gallery3d.filtershow.controller.ColorChooser;
@@ -79,7 +79,7 @@
         landscapeMap.put(ParameterColor.sParameterType, ColorChooser.class);
 
         portraitMap.put(ParameterInteger.sParameterType, BasicSlider.class);
-        landscapeMap.put(ParameterInteger.sParameterType, TitledSlider.class);
+        landscapeMap.put(ParameterInteger.sParameterType, BasicSlider.class);
         portraitMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class);
         landscapeMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class);
         portraitMap.put(ParameterStyles.sParameterType, StyleChooser.class);
@@ -115,12 +115,12 @@
         if (mShowParameter == SHOW_VALUE_INT & useCompact(context)) {
            if (getLocalRepresentation() instanceof FilterBasicRepresentation) {
             FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
-                apply += " " + effectName.toUpperCase() + " " + interval.getStateRepresentation();
+                apply += " " + effectName + " " + interval.getStateRepresentation();
            } else {
-                apply += " " + effectName.toUpperCase() + " " + parameterValue;
+                apply += " " + effectName + " " + parameterValue;
            }
         } else {
-            apply += " " + effectName.toUpperCase();
+            apply += " " + effectName;
         }
         return apply;
     }
@@ -135,7 +135,8 @@
     public void reflectCurrentFilter() {
         super.reflectCurrentFilter();
         if (getLocalRepresentation() != null
-                && getLocalRepresentation() instanceof FilterBasicRepresentation) {
+                && getLocalRepresentation() instanceof FilterBasicRepresentation
+                && mControl != null) {
             FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation();
             mControl.setPrameter(interval);
         }
@@ -164,19 +165,17 @@
     }
 
     @Override
-    public void setUtilityPanelUI(View actionButton, View editControl) {
-        mActionButton = actionButton;
+    public void setEditPanelUI(View editControl) {
         mEditControl = editControl;
         FilterRepresentation rep = getLocalRepresentation();
         Parameter param = getParameterToEdit(rep);
         if (param != null) {
             control(param, editControl);
         } else {
-            mSeekBar = new SeekBar(editControl.getContext());
-            LayoutParams lp = new LinearLayout.LayoutParams(
-                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
-            mSeekBar.setLayoutParams(lp);
-            ((LinearLayout) editControl).addView(mSeekBar);
+            mSeekBar = (SeekBar) editControl.findViewById(R.id.primarySeekBar);
+            if (mSeekBar != null && showsSeekBar()) {
+                mSeekBar.setVisibility(View.VISIBLE);
+            }
             mSeekBar.setOnSeekBarChangeListener(this);
         }
     }
diff --git a/src/com/android/gallery3d/filtershow/editors/SeeStraightEditor.java b/src/com/android/gallery3d/filtershow/editors/SeeStraightEditor.java
new file mode 100644
index 0000000..f320b4b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/SeeStraightEditor.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.filters.SeeStraightActs;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+
+public class SeeStraightEditor extends Editor {
+    public final static int ID = R.id.seeStraightEditor;
+    private final String LOGTAG = "SeeStraightEditor";
+
+    public SeeStraightEditor() {
+        super(ID);
+    }
+
+    protected SeeStraightEditor(int id) {
+        super(id);
+    }
+
+    public boolean useUtilityPanel() {
+        return true;
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mView = mImageShow = new ImageShow(context);
+    }
+
+    @Override
+    public void finalApplyCalled() {
+        super.finalApplyCalled();
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return false;
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/editors/TrueScannerEditor.java b/src/com/android/gallery3d/filtershow/editors/TrueScannerEditor.java
new file mode 100644
index 0000000..d184a3c
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/editors/TrueScannerEditor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.editors;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.SeekBar;
+
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
+import com.android.gallery3d.filtershow.imageshow.ImageShow;
+import com.android.gallery3d.filtershow.imageshow.ImageTrueScanner;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+
+import org.codeaurora.gallery.R;
+
+/**
+ * The editor with no slider for filters without UI
+ */
+public class TrueScannerEditor extends Editor{
+    public final static int ID = R.id.trueScannerEditor;
+    private final String LOGTAG = "TrueScannerEditor";
+    protected ImageTrueScanner mImageTrueScanner;
+
+    public TrueScannerEditor() {
+        super(ID);
+    }
+
+    public void initCords() {
+        mImageTrueScanner.setDetectedPoints(getPoints(MasterImage.getImage().getHighresImage()),
+                            MasterImage.getImage().getHighresImage().getWidth(),
+                            MasterImage.getImage().getHighresImage().getHeight());
+        mImageTrueScanner.invalidate();
+    }
+
+    @Override
+    public void createEditor(Context context, FrameLayout frameLayout) {
+        super.createEditor(context, frameLayout);
+        mView = mImageShow = mImageTrueScanner = new ImageTrueScanner(context);
+        mImageTrueScanner.setEditor(this);
+        mImageTrueScanner.setCordsUI(true);
+    }
+
+    @Override
+    public void finalApplyCalled() {
+        mImageTrueScanner.setCordsUI(false);
+        super.finalApplyCalled();
+    }
+
+    @Override
+    public boolean showsActionBar() {
+        return false;
+    }
+
+    @Override
+    public boolean showsSeekBar() {
+        return false;
+    }
+
+    private native int[] getPoints(Bitmap orgBitmap);
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
index 8350ff3..72fbdca 100644
--- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
+++ b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java
@@ -18,9 +18,20 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
+import android.net.Uri;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.data.FilterPresetDBHelper;
+import com.android.gallery3d.filtershow.data.FilterPresetSource;
+import com.android.gallery3d.filtershow.data.FilterPresetSource.SaveOption;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitBasic;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitImageOnly;
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 
 import java.util.ArrayList;
@@ -32,10 +43,23 @@
     protected HashMap<String, FilterRepresentation> mRepresentationLookup = null;
     private static final String LOGTAG = "BaseFiltersManager";
 
-    protected ArrayList<FilterRepresentation> mLooks = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mBorders = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>();
-    protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>();
+    protected ArrayList<FilterRepresentation> mLooks = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mBorders = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mTools = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mEffects = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mMakeup = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mDualCam = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mTrueScanner = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mHazeBuster = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mSeeStraight = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mTruePortrait = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mFilterPreset = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mWaterMarks = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mLocations = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mTimes = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mWeathers = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mEmotions = new ArrayList<>();
+    protected ArrayList<FilterRepresentation> mFoods = new ArrayList<>();
     private static int mImageBorderSize = 4; // in percent
 
     protected void init() {
@@ -43,6 +67,9 @@
         mRepresentationLookup = new HashMap<String, FilterRepresentation>();
         Vector<Class> filters = new Vector<Class>();
         addFilterClasses(filters);
+        addTrueScannerClasses(filters);
+        addHazeBusterClasses(filters);
+        addSeeStraightClasses(filters);
         for (Class filterClass : filters) {
             try {
                 Object filterInstance = filterClass.newInstance();
@@ -50,7 +77,7 @@
                     mFilters.put(filterClass, (ImageFilter) filterInstance);
 
                     FilterRepresentation rep =
-                        ((ImageFilter) filterInstance).getDefaultRepresentation();
+                            ((ImageFilter) filterInstance).getDefaultRepresentation();
                     if (rep != null) {
                         addRepresentation(rep);
                     }
@@ -140,6 +167,31 @@
         filters.add(ImageFilterFx.class);
         filters.add(ImageFilterBorder.class);
         filters.add(ImageFilterColorBorder.class);
+        filters.add(ImageFilterDualCamera.class);
+        filters.add(ImageFilterDualCamFusion.class);
+        filters.add(ImageFilterTruePortrait.class);
+        filters.add(ImageFilterTruePortraitFusion.class);
+        filters.add(ImageFilterPreset.class);
+        filters.add(SaveWaterMark.class);
+
+        if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
+            filters.add(ImageFilterMakeupWhiten.class);
+            filters.add(ImageFilterMakeupSoften.class);
+            filters.add(ImageFilterMakeupTrimface.class);
+            filters.add(ImageFilterMakeupBigeye.class);
+        }
+    }
+
+    protected void addTrueScannerClasses(Vector<Class> filters) {
+        filters.add(TrueScannerActs.class);
+    }
+
+    protected void addHazeBusterClasses(Vector<Class> filters) {
+        filters.add(HazeBusterActs.class);
+    }
+
+    protected void addSeeStraightClasses(Vector<Class> filters) {
+        filters.add(SeeStraightActs.class);
     }
 
     public ArrayList<FilterRepresentation> getLooks() {
@@ -150,6 +202,16 @@
         return mBorders;
     }
 
+    public ArrayList<FilterRepresentation> getDualCamera() {
+        return mDualCam;
+    }
+
+    public ArrayList<FilterRepresentation> getTruePortrait() {
+        return mTruePortrait;
+    }
+
+    public ArrayList<FilterRepresentation> getFilterPreset(){ return mFilterPreset; }
+
     public ArrayList<FilterRepresentation> getTools() {
         return mTools;
     }
@@ -158,8 +220,38 @@
         return mEffects;
     }
 
-    public void addBorders(Context context) {
+    public ArrayList<FilterRepresentation> getMakeup() {
+        return mMakeup;
+    }
+    public ArrayList<FilterRepresentation> getTrueScanner() {
+        return mTrueScanner;
+    }
+    public ArrayList<FilterRepresentation> getHazeBuster() {
+        return mHazeBuster;
+    }
+    public ArrayList<FilterRepresentation> getSeeStraight() {
+        return mSeeStraight;
+    }
+    public ArrayList<FilterRepresentation> getWaterMarks() {
+        return mWaterMarks;
+    }
+    public ArrayList<FilterRepresentation> getLocations() {
+        return mLocations;
+    }
+    public ArrayList<FilterRepresentation> getTimes() {
+        return mTimes;
+    }
+    public ArrayList<FilterRepresentation> getWeathers() {
+        return mWeathers;
+    }
+    public ArrayList<FilterRepresentation> getEmotions() {
+        return mEmotions;
+    }
+    public ArrayList<FilterRepresentation> getFoods() {
+        return mFoods;
+    }
 
+    public void addBorders(Context context) {
         // Do not localize
         String[] serializationNames = {
                 "FRAME_4X5",
@@ -267,42 +359,67 @@
                 "LUT3D_XPROCESS"
         };
 
+        int[] colorId = {
+                R.color.filtershow_color_none,
+                R.color.filtershow_color_punch,
+                R.color.filtershow_color_vintage,
+                R.color.filtershow_color_bw,
+                R.color.filtershow_color_bleach,
+                R.color.filtershow_color_instant,
+                R.color.filtershow_color_latte,
+                R.color.filtershow_color_blue,
+                R.color.filtershow_color_litho,
+                R.color.filtershow_color_xprocess
+        };
+
         FilterFxRepresentation nullFx =
                 new FilterFxRepresentation(context.getString(R.string.none),
                         0, R.string.none);
+        nullFx.setColorId(colorId[0]);
         mLooks.add(nullFx);
 
         for (int i = 0; i < drawid.length; i++) {
             FilterFxRepresentation fx = new FilterFxRepresentation(
                     context.getString(fxNameid[i]), drawid[i], fxNameid[i]);
             fx.setSerializationName(serializationNames[i]);
+            fx.setColorId(colorId[i] + 1);
             ImagePreset preset = new ImagePreset();
             preset.addFilter(fx);
             FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation(
                     context.getString(fxNameid[i]), preset, -1);
+            rep.setColorId(colorId[i] + 1);
             mLooks.add(rep);
             addRepresentation(fx);
         }
     }
 
     public void addEffects() {
-        mEffects.add(getRepresentation(ImageFilterTinyPlanet.class));
         mEffects.add(getRepresentation(ImageFilterWBalance.class));
         mEffects.add(getRepresentation(ImageFilterExposure.class));
-        mEffects.add(getRepresentation(ImageFilterVignette.class));
-        mEffects.add(getRepresentation(ImageFilterGrad.class));
         mEffects.add(getRepresentation(ImageFilterContrast.class));
-        mEffects.add(getRepresentation(ImageFilterShadows.class));
-        mEffects.add(getRepresentation(ImageFilterHighlights.class));
         mEffects.add(getRepresentation(ImageFilterVibrance.class));
         mEffects.add(getRepresentation(ImageFilterSharpen.class));
-        mEffects.add(getRepresentation(ImageFilterCurves.class));
-        mEffects.add(getRepresentation(ImageFilterHue.class));
-        mEffects.add(getRepresentation(ImageFilterChanSat.class));
-        mEffects.add(getRepresentation(ImageFilterBwFilter.class));
-        mEffects.add(getRepresentation(ImageFilterNegative.class));
-        mEffects.add(getRepresentation(ImageFilterEdge.class));
-        mEffects.add(getRepresentation(ImageFilterKMeans.class));
+    }
+
+    public void addMakeups(Context context) {
+        if(SimpleMakeupImageFilter.HAS_TS_MAKEUP) {
+            mMakeup.add(getRepresentation(ImageFilterMakeupWhiten.class));
+            mMakeup.add(getRepresentation(ImageFilterMakeupSoften.class));
+            mMakeup.add(getRepresentation(ImageFilterMakeupTrimface.class));
+            mMakeup.add(getRepresentation(ImageFilterMakeupBigeye.class));
+        }
+    }
+
+    public void addTrueScanner() {
+        mTrueScanner.add(getRepresentation(TrueScannerActs.class));
+    }
+
+    public void addHazeBuster() {
+        mHazeBuster.add(getRepresentation(HazeBusterActs.class));
+    }
+
+    public void addSeeStraight() {
+        mSeeStraight.add(getRepresentation(SeeStraightActs.class));
     }
 
     public void addTools(Context context) {
@@ -310,22 +427,19 @@
         int[] textId = {
                 R.string.crop,
                 R.string.straighten,
-                R.string.rotate,
-                R.string.mirror
+                R.string.rotate
         };
 
         int[] overlayId = {
-                R.drawable.filtershow_button_geometry_crop,
-                R.drawable.filtershow_button_geometry_straighten,
-                R.drawable.filtershow_button_geometry_rotate,
-                R.drawable.filtershow_button_geometry_flip
+                R.drawable.crop_crop,
+                R.drawable.crop_straighten,
+                R.drawable.crop_rotate
         };
 
         FilterRepresentation[] geometryFilters = {
                 new FilterCropRepresentation(),
                 new FilterStraightenRepresentation(),
-                new FilterRotateRepresentation(),
-                new FilterMirrorRepresentation()
+                new FilterRotateRepresentation()
         };
 
         for (int i = 0; i < textId.length; i++) {
@@ -340,11 +454,423 @@
         }
 
         //mTools.add(getRepresentation(ImageFilterRedEye.class));
-        mTools.add(getRepresentation(ImageFilterDraw.class));
+    }
+
+    public void addWaterMarks(Context context) {
+        int[] textId = {
+                R.string.watermark_location,
+                R.string.watermark_time,
+                R.string.watermark_weather,
+                R.string.watermark_emotions,
+                R.string.watermark_food
+        };
+
+        int[] overlayId = {
+                R.drawable.ic_watermark_location,
+                R.drawable.ic_watermark_time,
+                R.drawable.ic_watermark_weather,
+                R.drawable.ic_watermark_emotion,
+                R.drawable.ic_watermark_food
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_LOCATION,
+                        FilterWatermarkRepresentation.LOCATION),
+                new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_TIME,
+                        FilterWatermarkRepresentation.TIME),
+                new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_WEATHER,
+                        FilterWatermarkRepresentation.WEATHER),
+                new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_EMOTION,
+                        FilterWatermarkRepresentation.EMOTIONS),
+                new FilterWatermarkRepresentation(context, FilterWatermarkRepresentation.NAME_FOOD,
+                        FilterWatermarkRepresentation.FOOD)
+        };
+
+        for (int i = 0; i < textId.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i]);
+            waterMark.setOverlayOnly(true);
+            if (waterMark.getTextId() != 0) {
+                waterMark.setName(context.getString(waterMark.getTextId()));
+            }
+            mWaterMarks.add(waterMark);
+        }
+    }
+    public void addLocations(Context context) {
+        int[] textId = {
+                R.string.location_pin,
+                R.string.location_city,
+                R.string.location_hello,
+                R.string.location_stamp
+        };
+
+        int[] overlayId = {
+                R.drawable.icon_pin,
+                R.drawable.icon_city,
+                R.drawable.icon_hello,
+                R.drawable.icon_stamp
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, "LOCATION_PIN", "SAN DIEGO"),
+                new FilterWatermarkRepresentation(context, "LOCATION_CITY", "SAN DIEGO"),
+                new FilterWatermarkRepresentation(context, "LOCATION_HELLO","SAN DIEGO"),
+                new FilterWatermarkRepresentation(context, "LOCATION_STAMP","SAN DIEGO")
+        };
+
+        waterMarkFilters[0].new PositionInfo(0,
+                context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                0,0, Gravity.CENTER_HORIZONTAL);
+        waterMarkFilters[1].new PositionInfo(0,
+                context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                0,0, Gravity.CENTER_HORIZONTAL);
+        waterMarkFilters[2].new PositionInfo(0,60,0,0, Gravity.RIGHT, true);
+        waterMarkFilters[3].new PositionInfo(0,0,0,0, Gravity.CENTER);
+
+        for (int i = 0; i < waterMarkFilters.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i],
+                    new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+            waterMark.setWaterMarkId(overlayId[i]);
+            waterMark.setMarkType(0);
+            mLocations.add(waterMark);
+        }
+    }
+    public void addTimes(Context context) {
+        int[] textId = {
+                R.string.time_hourglass,
+                R.string.time_timestamp,
+                R.string.time_sunrise,
+                R.string.time_calendar
+        };
+
+        int[] overlayId = {
+                R.drawable.icon_hourglass,
+                R.drawable.icon_timestamp,
+                R.drawable.icon_sunrise,
+                R.drawable.icon_calendar
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, "TIME_HOURGLASS", null),
+                new FilterWatermarkRepresentation(context, "TIME_TIMESTAMP", null),
+                new FilterWatermarkRepresentation(context, "TIME_SUNRISE", null),
+                new FilterWatermarkRepresentation(context, "TIME_CALENDAR", null)
+        };
+
+        FilterWatermarkRepresentation.PositionInfo[] positionInfos = {
+                waterMarkFilters[0].new PositionInfo(
+                        context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                        0,0,0, Gravity.CENTER_VERTICAL),
+                waterMarkFilters[1].new PositionInfo(0,
+                        context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                        0,0, Gravity.CENTER_HORIZONTAL),
+                waterMarkFilters[2].new PositionInfo(0,
+                        context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                        0,0, Gravity.RIGHT),
+                waterMarkFilters[3].new PositionInfo(0,0,0,0, Gravity.CENTER)
+
+        };
+
+        for (int i = 0; i < waterMarkFilters.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i],
+                    new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+            waterMark.setWaterMarkId(overlayId[i]);
+            waterMark.setMarkType(1);
+            mTimes.add(waterMark);
+        }
+    }
+    public void addWeather(Context context) {
+        int[] textId = {
+                R.string.weather_rain,
+                R.string.weather_snow,
+                R.string.weather_sun,
+                R.string.weather_artistic_sun
+        };
+
+        int[] overlayId = {
+                R.drawable.icon_rain,
+                R.drawable.icon_snow,
+                R.drawable.icon_sun,
+                R.drawable.icon_artistic_sun
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, "WEATHER_RAIN", "50F"),
+                new FilterWatermarkRepresentation(context, "WEATHER_SNOW", "30F"),
+                new FilterWatermarkRepresentation(context, "WEATHER_SUN", "78F"),
+                new FilterWatermarkRepresentation(context, "WEATHER_ARTISTIC_SUN", "78F")
+        };
+
+        waterMarkFilters[0].new PositionInfo(84, 40, 0, 0, true);
+        waterMarkFilters[1].new PositionInfo(60, 50, 0, 0, true);
+        waterMarkFilters[2].new PositionInfo(0, 66, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+        waterMarkFilters[3].new PositionInfo(0, 56, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+
+        for (int i = 0; i < waterMarkFilters.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i],
+                    new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+            waterMark.setWaterMarkId(overlayId[i]);
+            waterMark.setMarkType(2);
+            mWeathers.add(waterMark);
+        }
+    }
+    public void addEmotions(Context context) {
+        int[] textId = {
+                R.string.emotion_party,
+                R.string.emotion_peace,
+                R.string.emotion_cry,
+                R.string.emotion_happy
+        };
+
+        int[] overlayId = {
+                R.drawable.icon_party,
+                R.drawable.icon_peace,
+                R.drawable.icon_cry,
+                R.drawable.icon_happy
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, "EMOTION_PARTY", "Party!!"),
+                new FilterWatermarkRepresentation(context, "EMOTION_PEACE", "PEACE"),
+                new FilterWatermarkRepresentation(context, "EMOTION_CRY", null),
+                new FilterWatermarkRepresentation(context, "EMOTION_HAPPY", null)
+        };
+
+        waterMarkFilters[0].new PositionInfo(0,
+                context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                0, 0, Gravity.CENTER_HORIZONTAL);
+        waterMarkFilters[1].new PositionInfo(0,
+                context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                0, 0, Gravity.CENTER_HORIZONTAL);
+
+        for (int i = 0; i < waterMarkFilters.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i],
+                    new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+            switch (i) {
+                case 2:
+                    waterMark.setWaterMarkId(R.drawable.icon_cry_color);
+                    waterMark.setMarkAlpha(255);
+                    break;
+                case 3:
+                    waterMark.setWaterMarkId(R.drawable.icon_happy_color);
+                    waterMark.setMarkAlpha(255);
+                    break;
+                default:
+                    waterMark.setWaterMarkId(overlayId[i]);
+                    break;
+            }
+            waterMark.setMarkType(3);
+            mEmotions.add(waterMark);
+        }
+    }
+    public void addFoods(Context context) {
+        int[] textId = {
+                R.string.food_fork_knife,
+                R.string.food_tea_time,
+                R.string.food_cheers,
+                R.string.food_yum
+        };
+
+        int[] overlayId = {
+                R.drawable.icon_fork_and_knife,
+                R.drawable.icon_tea_time,
+                R.drawable.icon_cheers,
+                R.drawable.icon_yum
+        };
+
+        FilterWatermarkRepresentation[] waterMarkFilters = {
+                new FilterWatermarkRepresentation(context, "FOOD_FORK_KNIFE", "Breakfast"),
+                new FilterWatermarkRepresentation(context, "FOOD_TEA_TIME", "Tea Time"),
+                new FilterWatermarkRepresentation(context, "FOOD_CHEERS", "Cheers"),
+                new FilterWatermarkRepresentation(context, "FOOD_YUM", null)
+        };
+
+        waterMarkFilters[0].new PositionInfo(0,32,0,0,Gravity.CENTER_HORIZONTAL,true);
+        waterMarkFilters[1].new PositionInfo(0,
+                context.getResources().getDimensionPixelSize(R.dimen.watermark_default_size),
+                0, 0, Gravity.CENTER_HORIZONTAL);
+        waterMarkFilters[2].new PositionInfo(0, 60, 0, 0, Gravity.CENTER_HORIZONTAL, true);
+
+        for (int i = 0; i < waterMarkFilters.length; i++) {
+            FilterWatermarkRepresentation waterMark = waterMarkFilters[i];
+            waterMark.setTextId(textId[i]);
+            waterMark.setOverlayId(overlayId[i],
+                    new ContextThemeWrapper(context, R.style.DefaultFillColor).getTheme());
+            waterMark.setWaterMarkId(overlayId[i]);
+            waterMark.setMarkType(4);
+            mFoods.add(waterMark);
+        }
+    }
+
+    public void addDualCam(Context context) {
+        int[] textId = {
+                R.string.focus,
+                R.string.halo,
+                R.string.motion,
+                R.string.posterize,
+                R.string.sketch,
+                R.string.zoom,
+                R.string.bw,
+                R.string.blackboard,
+                R.string.whiteboard,
+                R.string.dc_negative
+        };
+
+        int[] overlayId = {
+                R.drawable.focus,
+                R.drawable.halo,
+                R.drawable.motion,
+                R.drawable.posterize,
+                R.drawable.sketch,
+                R.drawable.zoom,
+                R.drawable.bw,
+                R.drawable.blackboard,
+                R.drawable.whiteboard,
+                R.drawable.negative
+        };
+
+        String[] serializationNames = {
+                "DUAL_CAM_FOCUS",
+                "DUAL_CAM_HALO",
+                "DUAL_CAM_MOTION",
+                "DUAL_CAM_POSTERIZE",
+                "DUAL_CAM_SKETCH",
+                "DUAL_CAM_ZOOM",
+                "DUAL_CAM_BW",
+                "DUAL_CAM_BLACKBOARD",
+                "DUAL_CAM_WHITEBOARD",
+                "DUAL_CAM_NEGATIVE"
+        };
+
+        // intensity range as defined by ddm lib
+        int[][] ranges = {
+                {0, 5, 10},
+                {0, 5, 10},
+                {0, 5, 10},
+                {0, 5, 10}
+        };
+
+        FilterDualCamBasicRepresentation representation = new FilterDualCamBasicRepresentation(
+                context.getString(R.string.none));
+        representation.setTextId(R.string.none);
+        representation.setEditorId(ImageOnlyEditor.ID);
+        representation.setSerializationName("DUAL_CAM_NONE");
+        mDualCam.add(representation);
+
+        for (int i = 0; i < textId.length; i++) {
+            if (i < ranges.length) {
+                representation = new FilterDualCamBasicRepresentation(context.getString(textId[i]),
+                        ranges[i][0], ranges[i][1], ranges[i][2]);
+            } else {
+                representation = new FilterDualCamBasicRepresentation(context.getString(textId[i]));
+            }
+            representation.setTextId(textId[i]);
+            representation.setOverlayId(overlayId[i]);
+            representation.setOverlayOnly(true);
+            representation.setSerializationName(serializationNames[i]);
+            mDualCam.add(representation);
+            addRepresentation(representation);
+        }
+
+        mDualCam.add(getRepresentation(ImageFilterDualCamFusion.class));
+    }
+
+    public void addTruePortrait(Context context) {
+        int[] textId = {
+                R.string.none,
+                R.string.blur,
+                R.string.motion_blur,
+                R.string.halo,
+                R.string.sketch
+        };
+
+        int[] overlayId = {
+                R.drawable.ic_tp_normal,
+                R.drawable.ic_tp_bokeh,
+                R.drawable.ic_tp_motion_blur,
+                R.drawable.ic_tp_halo,
+                R.drawable.ic_tp_sketch
+        };
+
+        String[] serializationNames = {
+                "TRUE_PORTRAIT_NONE",
+                "TRUE_PORTRAIT_BLUR",
+                "TRUE_PORTRAIT_MOTION_BLUR",
+                "TRUE_PORTRAIT_HALO",
+                "TRUE_PORTRAIT_SKETCH"
+        };
+
+        int[][] minMaxValues = {
+                {0,0,0},
+                {0,3,7},
+                {0,3,7},
+                {0,3,7},
+                {0,0,0}
+        };
+
+        boolean[] showParams = {
+                false,
+                true,
+                true,
+                true,
+                false
+        };
+
+        int[] editorIDs = {
+                ImageOnlyEditor.ID,
+                EditorTruePortraitBasic.ID,
+                EditorTruePortraitBasic.ID,
+                EditorTruePortraitBasic.ID,
+                EditorTruePortraitImageOnly.ID
+        };
+
+        for (int i = 0; i < textId.length; i++) {
+            FilterRepresentation tPortrait =
+                    new FilterBasicRepresentation(context.getString(textId[i]),
+                            minMaxValues[i][0], minMaxValues[i][1], minMaxValues[i][2]);
+            tPortrait.setFilterClass(ImageFilterTruePortrait.class);
+            tPortrait.setFilterType(FilterRepresentation.TYPE_TRUEPORTRAIT);
+            tPortrait.setTextId(textId[i]);
+            tPortrait.setOverlayId(overlayId[i]);
+            tPortrait.setOverlayOnly(true);
+            tPortrait.setSerializationName(serializationNames[i]);
+            tPortrait.setShowParameterValue(showParams[i]);
+            tPortrait.setEditorId(editorIDs[i]);
+            mTruePortrait.add(tPortrait);
+            addRepresentation(tPortrait);
+        }
+
+        mTruePortrait.add(getRepresentation(ImageFilterTruePortraitFusion.class));
+    }
+
+    public void addFilterPreset (Context context) {
+        FilterPresetSource fp = new FilterPresetSource(context);
+        ArrayList<SaveOption> ret = fp.getAllUserPresets();
+        if (ret == null) return;
+        for (int id = 0; id<ret.size(); id++){
+            FilterPresetRepresentation representation= new FilterPresetRepresentation (
+                    ret.get(id).name,ret.get(id)._id,id+1);
+            Uri filteredUri = Uri.parse(ret.get(id).Uri);
+            representation.setUri(filteredUri);
+            representation.setSerializationName("Custom");
+            mFilterPreset.add(representation);
+            ImagePreset preset = new ImagePreset();
+            preset.addFilter(representation);
+            addRepresentation(representation);
+        }
     }
 
     public void removeRepresentation(ArrayList<FilterRepresentation> list,
-                                          FilterRepresentation representation) {
+            FilterRepresentation representation) {
         for (int i = 0; i < list.size(); i++) {
             FilterRepresentation r = list.get(i);
             if (r.getFilterClass() == representation.getFilterClass()) {
@@ -359,5 +885,7 @@
         filterBorder.setResources(resources);
         ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class);
         filterFx.setResources(resources);
+        ImageFilterPreset filterPreset = (ImageFilterPreset) getFilter(ImageFilterPreset.class);
+        filterPreset.setResources(resources);
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
index 6c5274d..b009dfa 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java
@@ -19,7 +19,7 @@
 import android.util.JsonReader;
 import android.util.JsonWriter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
 import com.android.gallery3d.filtershow.controller.Parameter;
 import com.android.gallery3d.filtershow.controller.ParameterSet;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
index 5162927..99e9223 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java
@@ -20,7 +20,7 @@
 import android.util.JsonReader;
 import android.util.JsonWriter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
 import com.android.gallery3d.filtershow.controller.Parameter;
 import com.android.gallery3d.filtershow.controller.ParameterColor;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
index ba697d8..d209189 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java
@@ -20,7 +20,7 @@
 import android.util.JsonReader;
 import android.util.JsonWriter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorCrop;
 
 import java.io.IOException;
@@ -65,6 +65,9 @@
             return false;
         }
         FilterCropRepresentation crop = (FilterCropRepresentation) rep;
+        if (crop.isNil()) {
+            return true;
+        }
         if (mCrop.bottom != crop.mCrop.bottom
             || mCrop.left != crop.mCrop.left
             || mCrop.right != crop.mCrop.right
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
index edab2a0..9f77457 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java
@@ -4,7 +4,7 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.imageshow.ControlPoint;
 import com.android.gallery3d.filtershow.imageshow.Spline;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
index 48d3d90..0e867ac 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java
@@ -23,7 +23,7 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
 import com.android.gallery3d.filtershow.controller.BasicParameterStyle;
 import com.android.gallery3d.filtershow.controller.Parameter;
@@ -157,15 +157,20 @@
     private Vector<StrokeData> mDrawing = new Vector<StrokeData>();
     private StrokeData mCurrent; // used in the currently drawing style
 
-    public FilterDrawRepresentation() {
-        super("Draw");
+    public FilterDrawRepresentation(String name) {
+        super(name);
         setFilterClass(ImageFilterDraw.class);
-        setSerializationName("DRAW");
+        setSerializationName(name);
         setFilterType(FilterRepresentation.TYPE_VIGNETTE);
         setTextId(R.string.imageDraw);
         setEditorId(EditorDraw.ID);
         setOverlayId(R.drawable.filtershow_drawing);
         setOverlayOnly(true);
+        setDefaultColor();
+    }
+
+    private void setDefaultColor() {
+        mParamColor.setValue(DEFAULT_MENU_COLOR1);
     }
 
     @Override
@@ -185,7 +190,7 @@
 
     @Override
     public FilterRepresentation copy() {
-        FilterDrawRepresentation representation = new FilterDrawRepresentation();
+        FilterDrawRepresentation representation = new FilterDrawRepresentation(getName());
         copyAllParameters(representation);
         return representation;
     }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java
new file mode 100644
index 0000000..5010b7f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDualCamBasicRepresentation.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import java.io.IOException;
+
+import android.graphics.Point;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.filtershow.editors.EditorDualCamSketch;
+import com.android.gallery3d.filtershow.editors.EditorDualCamera;
+
+public class FilterDualCamBasicRepresentation extends FilterBasicRepresentation {
+    private static final String SERIAL_VALUE = "value";
+    private static final String SERIAL_POINT = "point";
+
+    private Point mPoint = new Point(-1, -1);
+
+    FilterDualCamBasicRepresentation(String name, int minVal, int defVal, int maxVal) {
+        super(name, minVal, defVal, maxVal);
+        setFilterType(FilterRepresentation.TYPE_DUALCAM);
+        setFilterClass(ImageFilterDualCamera.class);
+        setEditorId(minVal == maxVal ? EditorDualCamSketch.ID : EditorDualCamera.ID);
+        setShowParameterValue(true);
+    }
+
+    FilterDualCamBasicRepresentation(String name) {
+        this(name, 0, 0, 0);
+    }
+
+    @Override
+    public FilterRepresentation copy() {
+        FilterDualCamBasicRepresentation representation =
+                new FilterDualCamBasicRepresentation(getName(), 0,0,0);
+        copyAllParameters(representation);
+        return representation;
+    }
+
+    @Override
+    protected void copyAllParameters(FilterRepresentation representation) {
+        super.copyAllParameters(representation);
+        representation.useParametersFrom(this);
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        super.useParametersFrom(a);
+        if (a instanceof FilterDualCamBasicRepresentation) {
+            FilterDualCamBasicRepresentation representation = (FilterDualCamBasicRepresentation) a;
+            setPoint(representation.getPoint());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterDualCamBasicRepresentation) {
+            FilterDualCamBasicRepresentation dualCam = (FilterDualCamBasicRepresentation) representation;
+            if (dualCam.mPoint.equals(mPoint)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setPoint(int x, int y) {
+        mPoint = new Point(x,y);
+    }
+
+    public void setPoint(Point point) {
+        mPoint = point;
+    }
+
+    public Point getPoint() {
+        return mPoint;
+    }
+
+    @Override
+    public String toString() {
+        return "dualcam - value: " + getValue() + ", point: " + getPoint().toString();
+    }
+
+    // Serialization...
+
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+        {
+            writer.name(NAME_TAG);
+            writer.value(getName());
+            writer.name(SERIAL_VALUE);
+            writer.value(getValue());
+            writer.name(SERIAL_POINT);
+            writer.beginArray();
+            writer.value(mPoint.x);
+            writer.value(mPoint.y);
+            writer.endArray();
+        }
+        writer.endObject();
+    }
+
+    public void deSerializeRepresentation(JsonReader reader) throws IOException {
+        reader.beginObject();
+        while (reader.hasNext()) {
+            String name = reader.nextName();
+            if (name.equalsIgnoreCase(NAME_TAG)) {
+                setName(reader.nextString());
+            } else if (name.equalsIgnoreCase(SERIAL_VALUE)) {
+                setValue(reader.nextInt());
+            } else if (name.equalsIgnoreCase(SERIAL_POINT)) {
+                reader.beginArray();
+                reader.hasNext();
+                mPoint.x = reader.nextInt();
+                reader.hasNext();
+                mPoint.y = reader.nextInt();
+                reader.endArray();
+            } else {
+                reader.skipValue();
+            }
+        }
+        reader.endObject();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java
new file mode 100644
index 0000000..cd3a2e6
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterDualCamFusionRepresentation.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import java.io.IOException;
+
+import android.graphics.Point;
+import android.net.Uri;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
+
+import org.codeaurora.gallery.R;
+
+
+public class FilterDualCamFusionRepresentation extends FilterDualCamBasicRepresentation
+        implements FilterFusionRepresentation {
+    private static final String LOGTAG = "FilterFusionRepresentation";
+    public static final String SERIALIZATION_NAME = "FUSION";
+
+    private static final String SERIAL_UNDERLAY_IMAGE = "image";
+    private static final String SERIAL_POINT = "point";
+
+    private Point mPoint = new Point(-1, -1);
+    private String mUri = "";
+
+    public FilterDualCamFusionRepresentation() {
+        super("Fusion");
+        setSerializationName(SERIALIZATION_NAME);
+        setFilterType(FilterRepresentation.TYPE_DUALCAM);
+        setFilterClass(ImageFilterDualCamFusion.class);
+        setEditorId(EditorDualCamFusion.ID);
+        setShowParameterValue(false);
+        setTextId(R.string.fusion);
+        setOverlayId(R.drawable.fusion);
+        setOverlayOnly(true);
+    }
+
+    @Override
+    public FilterRepresentation copy() {
+        FilterDualCamFusionRepresentation representation =
+                new FilterDualCamFusionRepresentation();
+        copyAllParameters(representation);
+        return representation;
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        super.useParametersFrom(a);
+        if (a instanceof FilterDualCamFusionRepresentation) {
+            FilterDualCamFusionRepresentation representation = (FilterDualCamFusionRepresentation) a;
+            setPoint(representation.getPoint());
+            setUnderlay(representation.getUnderlay());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterDualCamFusionRepresentation) {
+            FilterDualCamFusionRepresentation fusion = (FilterDualCamFusionRepresentation) representation;
+            if (fusion.mPoint.equals(mPoint) && fusion.mUri.equals(mUri)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void setPoint(int x, int y) {
+        mPoint = new Point(x,y);
+    }
+
+    public void setPoint(Point point) {
+        mPoint = point;
+    }
+
+    public Point getPoint() {
+        return mPoint;
+    }
+
+    @Override
+    public void setUnderlay(Uri uri) {
+        if (uri != null) {
+            mUri = uri.toString();
+        } else {
+            mUri = "";
+        }
+    }
+
+    @Override
+    public void setUnderlay(String uri) {
+        if (uri != null)
+            mUri = uri;
+        else
+            mUri = "";
+    }
+
+    @Override
+    public boolean hasUnderlay() {
+        return (mUri != null) && (!mUri.isEmpty());
+    }
+
+    @Override
+    public String getUnderlay() {
+        return mUri;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("fusion - underlay: ").append(getUnderlay());
+        sb.append(", point: ").append(getPoint().toString());
+
+        return sb.toString();
+    }
+
+    // Serialization...
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+        {
+            writer.name(NAME_TAG);
+            writer.value(getName());
+            writer.name(SERIAL_UNDERLAY_IMAGE);
+            writer.value(mUri);
+            writer.name(SERIAL_POINT);
+            writer.beginArray();
+            writer.value(mPoint.x);
+            writer.value(mPoint.y);
+            writer.endArray();
+        }
+        writer.endObject();
+    }
+
+    public void deSerializeRepresentation(JsonReader reader) throws IOException {
+        reader.beginObject();
+        while (reader.hasNext()) {
+            String name = reader.nextName();
+            if (name.equalsIgnoreCase(NAME_TAG)) {
+                setName(reader.nextString());
+            } else if (name.equalsIgnoreCase(SERIAL_UNDERLAY_IMAGE)) {
+                setUnderlay(reader.nextString());
+            } else if (name.equalsIgnoreCase(SERIAL_POINT)) {
+                reader.beginArray();
+                reader.hasNext();
+                mPoint.x = reader.nextInt();
+                reader.hasNext();
+                mPoint.y = reader.nextInt();
+                reader.endArray();
+            } else {
+                reader.skipValue();
+            }
+        }
+        reader.endObject();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFusionRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFusionRepresentation.java
new file mode 100644
index 0000000..ba12be5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterFusionRepresentation.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.net.Uri;
+
+public interface FilterFusionRepresentation {
+    void setUnderlay(Uri uri);
+    void setUnderlay(String uri);
+    boolean hasUnderlay();
+    String getUnderlay();
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
index 928c3ea..34d8c94 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java
@@ -19,7 +19,7 @@
 import android.util.JsonReader;
 import android.util.JsonWriter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorGrad;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.imageshow.Line;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
index f310a2b..11b9a0f 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
 public class FilterImageBorderRepresentation extends FilterRepresentation {
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
index c281443..67d1959 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java
@@ -20,7 +20,7 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorMirror;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java
new file mode 100644
index 0000000..96a33f0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterPresetRepresentation.java
@@ -0,0 +1,162 @@
+/*
+ * 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.gallery3d.filtershow.filters;
+
+import android.net.Uri;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
+
+import java.io.IOException;
+
+public class FilterPresetRepresentation extends FilterRepresentation {
+
+    private static final String LOGTAG = "FilterPresetRepresentation";
+
+    private static final String URI_TAG = "URI";
+
+    // TODO: When implementing serialization, we should find a unique way of
+    // specifying bitmaps / names (the resource IDs being random)
+    private int mBitmapResource = 0;
+    private int mNameResource = 0;
+    private Uri FilteredURI;
+    //private int mId;
+
+    public FilterPresetRepresentation(String name, int bitmapResource, int nameResource) {
+        super(name);
+        setFilterClass(ImageFilterPreset.class);
+        mBitmapResource = bitmapResource;
+        mNameResource = nameResource;
+        setFilterType(FilterRepresentation.TYPE_PRESETFILTER);
+        setEditorId(ImageOnlyEditor.ID);
+        setShowParameterValue(false);
+        setSupportsPartialRendering(true);
+    }
+
+    @Override
+    public String toString() {
+        return "FilterPreset: " + hashCode() + " : " + getName() + " bitmap rsc: " + mBitmapResource;
+    }
+
+    @Override
+    public FilterRepresentation copy() {
+        FilterPresetRepresentation representation = new FilterPresetRepresentation(getName(), 0, 0);
+        copyAllParameters(representation);
+        return representation;
+    }
+
+    @Override
+    protected void copyAllParameters(FilterRepresentation representation) {
+        super.copyAllParameters(representation);
+        representation.useParametersFrom(this);
+    }
+
+    @Override
+    public synchronized void useParametersFrom(FilterRepresentation a) {
+        if (a instanceof FilterPresetRepresentation) {
+            FilterPresetRepresentation representation = (FilterPresetRepresentation) a;
+            setName(representation.getName());
+            setSerializationName(representation.getSerializationName());
+            setBitmapResource(representation.getBitmapResource());
+            setNameResource(representation.getNameResource());
+            setUri(representation.getUri());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterPresetRepresentation) {
+            FilterPresetRepresentation fp = (FilterPresetRepresentation) representation;
+            if (fp.mNameResource == mNameResource
+                   && fp.mBitmapResource == mBitmapResource) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean same(FilterRepresentation representation) {
+        if (!super.same(representation)) {
+            return false;
+        }
+        return equals(representation);
+    }
+
+    public void setUri (Uri URI) {FilteredURI = URI;}
+
+    public Uri getUri(){return FilteredURI;}
+
+    public void setId (int Id) {mBitmapResource = Id;}
+
+    public int getId() {
+        return mBitmapResource;
+    }
+
+    @Override
+    public boolean allowsSingleInstanceOnly() {
+        return true;
+    }
+
+    public int getNameResource() {
+        return mNameResource;
+    }
+
+    public void setNameResource(int nameResource) {
+            mNameResource = nameResource;
+    }
+
+    public int getBitmapResource() {
+        return mBitmapResource;
+    }
+
+    public void setBitmapResource(int bitmapResource) {
+            mBitmapResource = bitmapResource;
+    }
+
+    // Serialization...
+
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+        {
+            writer.name(NAME_TAG);
+            writer.value(getName());
+            writer.name(URI_TAG);
+            writer.value(getUri().toString());
+        }
+        writer.endObject();
+    }
+
+    public void deSerializeRepresentation(JsonReader reader) throws IOException {
+        reader.beginObject();
+        while (reader.hasNext()) {
+            String name = reader.nextName();
+            if (name.equalsIgnoreCase(NAME_TAG)) {
+                setName(reader.nextString());
+            } else if (name.equalsIgnoreCase(URI_TAG)) {
+                setUri(Uri.parse(reader.nextString()));
+            } else {
+                reader.skipValue();
+            }
+        }
+            reader.endObject();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
index dd06a97..68cf0d6 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java
@@ -18,7 +18,7 @@
 
 import android.graphics.RectF;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorRedEye;
 
 import java.util.Vector;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
index 0fb157d..dae2de8 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java
@@ -16,6 +16,8 @@
 
 package com.android.gallery3d.filtershow.filters;
 
+import android.content.res.Resources;
+import android.text.TextUtils;
 import android.util.JsonReader;
 import android.util.JsonWriter;
 import android.util.Log;
@@ -36,9 +38,12 @@
     private int mEditorId = BasicEditor.ID;
     private int mButtonId = 0;
     private int mOverlayId = 0;
+    private int mColorId = 0;
     private boolean mOverlayOnly = false;
     private boolean mShowParameterValue = true;
     private boolean mIsBooleanFilter = false;
+    private boolean isSvgOverlay = false;
+    private Resources.Theme currentTheme;
     private String mSerializationName;
     public static final byte TYPE_BORDER = 1;
     public static final byte TYPE_FX = 2;
@@ -47,15 +52,26 @@
     public static final byte TYPE_NORMAL = 5;
     public static final byte TYPE_TINYPLANET = 6;
     public static final byte TYPE_GEOMETRY = 7;
+    public static final byte TYPE_MAKEUP = 8;
+    public static final byte TYPE_DUALCAM = 9;
+    public static final byte TYPE_TRUEPORTRAIT = 10;
+    public static final byte TYPE_PRESETFILTER = 11;
+    public static final byte TYPE_WATERMARK_CATEGORY = 12;
+    public static final byte TYPE_WATERMARK = 13;
     protected static final String NAME_TAG = "Name";
 
     public FilterRepresentation(String name) {
         mName = name;
+        mSerializationName = name.toUpperCase();
     }
 
     public FilterRepresentation copy(){
         FilterRepresentation representation = new FilterRepresentation(mName);
         representation.useParametersFrom(this);
+        if (getFilterType() == TYPE_WATERMARK) {
+            representation.setSerializationName(getSerializationName());
+            representation.setFilterType(TYPE_WATERMARK);
+        }
         return representation;
     }
 
@@ -89,12 +105,21 @@
                 && representation.mOverlayId == mOverlayId
                 && representation.mOverlayOnly == mOverlayOnly
                 && representation.mShowParameterValue == mShowParameterValue
-                && representation.mIsBooleanFilter == mIsBooleanFilter) {
+                && representation.mIsBooleanFilter == mIsBooleanFilter
+                && representation.mColorId == mColorId) {
             return true;
         }
         return false;
     }
 
+    public int getColorId() {
+        return mColorId;
+    }
+
+    public void setColorId(int colorId) {
+        mColorId = colorId;
+    }
+
     public boolean isBooleanFilter() {
         return mIsBooleanFilter;
     }
@@ -185,6 +210,19 @@
         mOverlayId = overlayId;
     }
 
+    public void setOverlayId(int overlayId, Resources.Theme theme) {
+        mOverlayId = overlayId;
+        currentTheme = theme;
+    }
+
+    public Resources.Theme getCurrentTheme() {
+        return currentTheme;
+    }
+
+    public void setCurrentTheme(Resources.Theme theme) {
+        currentTheme = theme;
+    }
+
     public boolean getOverlayOnly() {
         return mOverlayOnly;
     }
@@ -193,6 +231,14 @@
         mOverlayOnly = value;
     }
 
+    public boolean isSvgOverlay() {
+        return isSvgOverlay;
+    }
+
+    public void setSvgOverlay(boolean svgOverlay) {
+        isSvgOverlay = svgOverlay;
+    }
+
     final public int getEditorId() {
         return mEditorId;
     }
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
index 4299dd3..9c321f0 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java
@@ -20,7 +20,7 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorRotate;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
@@ -103,6 +103,23 @@
         }
     }
 
+    public void rotateCCW() {
+        switch(mRotation) {
+            case ZERO:
+                mRotation = Rotation.TWO_SEVENTY;
+                break;
+            case NINETY:
+                mRotation = Rotation.ZERO;
+                break;
+            case ONE_EIGHTY:
+                mRotation = Rotation.NINETY;
+                break;
+            case TWO_SEVENTY:
+                mRotation = Rotation.ONE_EIGHTY;
+                break;
+        }
+    }
+
     public void set(FilterRotateRepresentation r) {
         mRotation = r.mRotation;
     }
@@ -114,6 +131,10 @@
         mRotation = rotation;
     }
 
+    public void resetRotation() {
+        mRotation = Rotation.ZERO;
+    }
+
     @Override
     public boolean allowsSingleInstanceOnly() {
         return true;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
index 1ba80e8..ebff5ab 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java
@@ -20,7 +20,7 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorStraighten;
 
 import java.io.IOException;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
index 4f7bc6a..172e060 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorTinyPlanet;
 
 public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation {
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTruePortraitFusionRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTruePortraitFusionRepresentation.java
new file mode 100644
index 0000000..3864eac
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterTruePortraitFusionRepresentation.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import java.io.IOException;
+
+import android.net.Uri;
+import android.util.JsonReader;
+import android.util.JsonWriter;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitFusion;
+
+
+public class FilterTruePortraitFusionRepresentation extends FilterRepresentation implements FilterFusionRepresentation {
+    private static final String LOGTAG = "FilterTruePortraitFusionRepresentation";
+    public static final String SERIALIZATION_NAME = "TP_FUSION";
+    private static final String SERIAL_UNDERLAY_IMAGE = "image";
+
+    private String mUri = "";
+
+    public FilterTruePortraitFusionRepresentation() {
+        super("Fusion");
+        setSerializationName(SERIALIZATION_NAME);
+        setFilterType(FilterRepresentation.TYPE_TRUEPORTRAIT);
+        setFilterClass(ImageFilterTruePortraitFusion.class);
+        setEditorId(EditorTruePortraitFusion.ID);
+        setShowParameterValue(false);
+        setTextId(R.string.fusion);
+        setOverlayId(R.drawable.ic_tp_fusion);
+        setOverlayOnly(true);
+    }
+
+    @Override
+    public FilterRepresentation copy() {
+        FilterTruePortraitFusionRepresentation representation =
+                new FilterTruePortraitFusionRepresentation();
+        copyAllParameters(representation);
+        return representation;
+    }
+
+    @Override
+    protected void copyAllParameters(FilterRepresentation representation) {
+        super.copyAllParameters(representation);
+        representation.useParametersFrom(this);
+    }
+
+    public void useParametersFrom(FilterRepresentation a) {
+        super.useParametersFrom(a);
+        if (a instanceof FilterTruePortraitFusionRepresentation) {
+            FilterTruePortraitFusionRepresentation representation = (FilterTruePortraitFusionRepresentation) a;
+            setUnderlay(representation.getUnderlay());
+        }
+    }
+
+    @Override
+    public boolean equals(FilterRepresentation representation) {
+        if (!super.equals(representation)) {
+            return false;
+        }
+        if (representation instanceof FilterTruePortraitFusionRepresentation) {
+            FilterTruePortraitFusionRepresentation fusion = (FilterTruePortraitFusionRepresentation) representation;
+            if (fusion.mUri.equals(mUri)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void setUnderlay(Uri uri) {
+        if(uri != null) {
+            mUri = uri.toString();
+        } else {
+            mUri = "";
+        }
+    }
+
+    @Override
+    public void setUnderlay(String uri) {
+        if(uri != null)
+            mUri = uri;
+        else
+            mUri = "";
+    }
+
+    @Override
+    public boolean hasUnderlay() {
+        return (mUri != null) && (mUri.isEmpty() == false);
+    }
+
+    @Override
+    public String getUnderlay() {
+        return mUri;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("fusion - underlay: ").append(getUnderlay());
+
+        return sb.toString();
+    }
+
+    // Serialization...
+    public void serializeRepresentation(JsonWriter writer) throws IOException {
+        writer.beginObject();
+        {
+            writer.name(NAME_TAG);
+            writer.value(getName());
+            writer.name(SERIAL_UNDERLAY_IMAGE);
+            writer.value(mUri);
+        }
+        writer.endObject();
+    }
+
+    public void deSerializeRepresentation(JsonReader reader) throws IOException {
+        reader.beginObject();
+        while (reader.hasNext()) {
+            String name = reader.nextName();
+            if (name.equalsIgnoreCase(NAME_TAG)) {
+                setName(reader.nextString());
+            } else if (name.equalsIgnoreCase(SERIAL_UNDERLAY_IMAGE)) {
+                setUnderlay(reader.nextString());
+            } else {
+                reader.skipValue();
+            }
+        }
+        reader.endObject();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
index 512594f..e90e12f 100644
--- a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
+++ b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java
@@ -19,7 +19,7 @@
 import android.util.JsonReader;
 import android.util.JsonWriter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.controller.BasicParameterInt;
 import com.android.gallery3d.filtershow.controller.Parameter;
 import com.android.gallery3d.filtershow.editors.EditorVignette;
diff --git a/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java
new file mode 100644
index 0000000..3774979
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/FilterWatermarkRepresentation.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.filtershow.filters;
+
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.Gravity;
+
+import com.android.gallery3d.filtershow.category.WaterMarkView;
+
+import org.codeaurora.gallery.R;
+
+public class FilterWatermarkRepresentation extends FilterRepresentation {
+    public static final String NAME_LOCATION = "LOCATION";
+    public static final String NAME_TIME = "TIME";
+    public static final String NAME_WEATHER = "WEATHER";
+    public static final String NAME_EMOTION = "EMOTION";
+    public static final String NAME_FOOD = "FOOD";
+
+    public static final int LOCATION = 12;
+    public static final int TIME = 13;
+    public static final int WEATHER = 14;
+    public static final int EMOTIONS = 15;
+    public static final int FOOD = 16;
+    private int adapterId;
+    private int waterMarkId;
+    private int markAlpha = -1;
+    private int markType = -1;
+    private String textHint = "HELLO";
+    private PositionInfo positionInfo;
+    private Context mContext;
+    private WaterMarkView currentMarkView;
+
+    //for main panel
+    public FilterWatermarkRepresentation(Context context, String name, int category) {
+        this(name);
+        mContext = context;
+        setFilterType(FilterRepresentation.TYPE_WATERMARK_CATEGORY);
+        loadCategory(category);
+    }
+
+    //for level-2 panel
+    public FilterWatermarkRepresentation(Context context, String name, String textHint) {
+        this(name);
+        mContext = context;
+        setFilterClass(SaveWaterMark.class);
+        setName("");
+        setFilterType(FilterRepresentation.TYPE_WATERMARK);
+        setCurrentTheme(new ContextThemeWrapper(mContext, R.style.DefaultFillColor).getTheme());
+        if (textHint != null) {
+            this.textHint = textHint;
+        }
+    }
+
+    public FilterWatermarkRepresentation(String name) {
+        super(name);
+        setSerializationName(name);
+        setShowParameterValue(false);
+        setSupportsPartialRendering(true);
+        setSvgOverlay(true);
+        setOverlayOnly(true);
+    }
+
+    private void loadCategory(int category) {
+        switch (category) {
+            case LOCATION:
+                setAdapterId(LOCATION);
+                break;
+            case TIME:
+                setAdapterId(TIME);
+                break;
+            case WEATHER:
+                setAdapterId(WEATHER);
+                break;
+            case EMOTIONS:
+                setAdapterId(EMOTIONS);
+                break;
+            case FOOD:
+                setAdapterId(FOOD);
+                break;
+        }
+    }
+
+    public int getAdapterId() {
+        return adapterId;
+    }
+
+    public void setAdapterId(int adapterId) {
+        this.adapterId = adapterId;
+    }
+
+
+    public int getWaterMarkId() {
+        return waterMarkId;
+    }
+
+    public void setWaterMarkId(int waterMarkId) {
+        this.waterMarkId = waterMarkId;
+    }
+
+    public void setMarkAlpha(int alpha) {
+        markAlpha = alpha;
+    }
+
+    public WaterMarkView getWaterMarkView() {
+        return getWaterMarkView(textHint);
+    }
+
+    public WaterMarkView getWaterMarkView(String textHint) {
+        if (currentMarkView != null) {
+            return currentMarkView;
+        }
+        currentMarkView = new WaterMarkView(mContext,
+                mContext.getResources().getDrawable(getWaterMarkId(), getCurrentTheme()), textHint);
+        if (positionInfo != null) {
+            currentMarkView.setTextPosition(positionInfo.marginLeft, positionInfo.marginTop,
+                    positionInfo.marginRight, positionInfo.marginBottom, positionInfo.gravity, positionInfo.isDip);
+        } else {
+            currentMarkView.setTextVisibility(false);
+        }
+        currentMarkView.setImageAlpha(markAlpha >= 0 ? markAlpha : 128);
+        return currentMarkView;
+    }
+
+    public void setMarkType(int markType) {
+        this.markType = markType;
+    }
+
+    public int getMarkType() {
+        return markType;
+    }
+
+    public void setTextHint(String textHint) {
+        this.textHint = textHint;
+    }
+
+    public String getTextHint() {
+        return textHint;
+    }
+
+    public void reset() {
+        currentMarkView = null;
+    }
+
+    protected class PositionInfo {
+        protected int marginLeft;
+        protected int marginTop;
+        protected int marginRight;
+        protected int marginBottom;
+        protected int gravity;
+        protected boolean isDip;
+        public PositionInfo() {
+            this(0, 0, 0, 0, Gravity.NO_GRAVITY, false);
+        }
+
+        public PositionInfo(int left, int top, int right, int bottom) {
+            this(left, top, right, bottom, Gravity.NO_GRAVITY, false);
+        }
+
+        public PositionInfo(int left, int top, int right, int bottom, int gravity) {
+            this(left, top, right, bottom, gravity, false);
+        }
+
+        public PositionInfo(int left, int top, int right, int bottom, boolean isDip) {
+            this(left, top, right, bottom, Gravity.NO_GRAVITY, isDip);
+        }
+
+        public PositionInfo(int left, int top, int right, int bottom, int gravity, boolean isDip) {
+            marginLeft = left;
+            marginTop = top;
+            marginRight = right;
+            marginBottom = bottom;
+            this.gravity = gravity;
+            this.isDip = isDip;
+            FilterWatermarkRepresentation.this.positionInfo = PositionInfo.this;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/HazeBusterActs.java b/src/com/android/gallery3d/filtershow/filters/HazeBusterActs.java
new file mode 100644
index 0000000..a62e0c9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/HazeBusterActs.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.util.Log;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.editors.HazeBusterEditor;
+
+import static com.android.gallery3d.filtershow.imageshow.ImageTrueScanner.*;
+
+public class HazeBusterActs extends SimpleImageFilter {
+    public static final String SERIALIZATION_NAME = "HazeBusterActs";
+    private static final boolean DEBUG = true;
+    private static final int MIN_WIDTH = 512;
+    private static final int MIN_HEIGHT = 512;
+    private static final String TAG = "HazeBuster";
+    private static boolean isHazeBusterEnabled = true;
+
+
+    private void printDebug(String str) {
+        if(DEBUG)
+            android.util.Log.d(TAG, str);
+    }
+
+    public static boolean isHazeBusterEnabled() {
+        return isHazeBusterEnabled;
+    }
+
+    public HazeBusterActs() {
+        mName = "HazeBusterActs";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("HazeBuster");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(HazeBusterActs.class);
+        representation.setTextId(R.string.hazebuster_acts);
+        representation.setSupportsPartialRendering(false);
+        representation.setIsBooleanFilter(true);
+        representation.setShowParameterValue(false);
+        representation.setValue(0);
+        representation.setDefaultValue(0);
+        representation.setMinimum(0);
+        representation.setMaximum(0);
+        representation.setEditorId(HazeBusterEditor.ID);
+
+        return representation;
+    }
+
+    private native boolean processImage(Bitmap bitmap, int width, int height, Bitmap dstBitmap);
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float not_use, int quality) {
+        if(bitmap == null)
+            return null;
+
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+        if(width <= MIN_WIDTH && height <= MIN_HEIGHT)
+            return bitmap;
+
+        Bitmap outBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        if(!processImage(bitmap, width, height, outBitmap)) {
+            Log.e(TAG, "Image error on processing");
+            return bitmap;
+        }
+
+        return outBitmap;
+    }
+
+    static {
+        try {
+            System.loadLibrary("jni_hazebuster");
+            isHazeBusterEnabled = true;
+        } catch(UnsatisfiedLinkError e) {
+            isHazeBusterEnabled = false;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
index e2a0147..8f22bbe 100644
--- a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
+++ b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java
@@ -20,7 +20,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class IconUtilities {
     public static final int PUNCH = R.drawable.filtershow_fx_0005_punch;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
old mode 100644
new mode 100755
index 1fcd300..bf3d02c
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java
@@ -22,6 +22,7 @@
 import android.renderscript.Allocation;
 import android.widget.Toast;
 
+import com.android.gallery3d.app.GalleryAppImpl;
 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
@@ -35,7 +36,9 @@
     // TODO: Temporary, for dogfood note memory issues with toasts for better
     // feedback. Remove this when filters actually work in low memory
     // situations.
-    private static Activity sActivity = null;
+    protected static Activity sActivity = null;
+    private static Toast sToast = null;
+    private String lastMsg;
 
     public static void setActivityForMemoryToasts(Activity activity) {
         sActivity = activity;
@@ -43,19 +46,38 @@
 
     public static void resetStatics() {
         sActivity = null;
+        if (null != sToast) {
+            sToast.cancel();
+        }
+        sToast = null;
+    }
+
+    void showToast(String msg, int duration) {
+        if (sActivity != null) {
+            sActivity.runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    if (sActivity != null && (!msg.equals(lastMsg) || sToast == null)) {
+                        sToast = Toast.makeText(GalleryAppImpl.getContext(), msg, duration);
+                        lastMsg = msg;
+                    }
+                    if (sToast != null) {
+                        sToast.show();
+                    }
+                }
+            });
+        }
+    }
+
+    void showToast(int resID, int duration) {
+        showToast(GalleryAppImpl.getContext().getString(resID), duration);
     }
 
     public void freeResources() {}
 
     public void displayLowMemoryToast() {
-        if (sActivity != null) {
-            sActivity.runOnUiThread(new Runnable() {
-                public void run() {
-                    Toast.makeText(sActivity, "Memory too low for filter " + getName() +
-                            ", please file a bug report", Toast.LENGTH_SHORT).show();
-                }
-            });
-        }
+        showToast("Memory too low for filter " + getName() +
+                ", please file a bug report", Toast.LENGTH_SHORT);
     }
 
     public void setName(String name) {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
index a7286f0..95d2554 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java
@@ -16,6 +16,9 @@
 
 package com.android.gallery3d.filtershow.filters;
 
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -23,8 +26,8 @@
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
-
-import java.util.HashMap;
+import android.util.DisplayMetrics;
+import android.util.Log;
 
 public class ImageFilterBorder extends ImageFilter {
     private static final float NINEPATCH_ICON_SCALING = 10;
@@ -32,7 +35,7 @@
     private FilterImageBorderRepresentation mParameters = null;
     private Resources mResources = null;
 
-    private HashMap<Integer, Drawable> mDrawables = new HashMap<Integer, Drawable>();
+    private HashMap<Integer, WeakReference<Drawable>> mDrawables = new HashMap<Integer, WeakReference<Drawable>>();
 
     public ImageFilterBorder() {
         mName = "Border";
@@ -70,6 +73,7 @@
         }
         float scale2 = scaleFactor * 2.0f;
         float scale1 = 1 / scale2;
+
         return applyHelper(bitmap, scale1, scale2);
     }
 
@@ -81,10 +85,16 @@
     }
 
     public Drawable getDrawable(int rsc) {
-        Drawable drawable = mDrawables.get(rsc);
+        Drawable drawable = (mDrawables.get(rsc) != null) ? mDrawables.get(rsc).get() : null;
         if (drawable == null && mResources != null && rsc != 0) {
-            drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc));
-            mDrawables.put(rsc, drawable);
+            DisplayMetrics dm = mResources.getDisplayMetrics();
+            BitmapFactory.Options opt = new BitmapFactory.Options();
+            if(dm.densityDpi > DisplayMetrics.DENSITY_MEDIUM) {
+                opt.inTargetDensity = DisplayMetrics.DENSITY_MEDIUM;
+            }
+            drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc, opt));
+            //drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc));
+            mDrawables.put(rsc, new WeakReference<Drawable>(drawable));
         }
         return drawable;
     }
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
index 50837ca..9a012d6 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 import android.graphics.Color;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
index 8482eac..dd8d31d 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java
@@ -24,7 +24,7 @@
 import android.renderscript.Script.LaunchOptions;
 import android.renderscript.Type;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
 
 public class ImageFilterChanSat extends ImageFilterRS {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
index 27c0e08..c11cb79 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
index efb9cde..ad7cbd7 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java
@@ -20,7 +20,7 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
index 8fd5b02..77dfa17 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java
@@ -28,7 +28,8 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.app.GalleryAppImpl;
 import com.android.gallery3d.app.Log;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
@@ -47,7 +48,8 @@
     int mCachedStrokes = -1;
     int mCurrentStyle = 0;
 
-    FilterDrawRepresentation mParameters = new FilterDrawRepresentation();
+    FilterDrawRepresentation mParameters = new FilterDrawRepresentation(
+            GalleryAppImpl.getContext().getString(R.string.imageDraw));
 
     public ImageFilterDraw() {
         mName = "Image Draw";
@@ -69,7 +71,8 @@
 
     @Override
     public FilterRepresentation getDefaultRepresentation() {
-        return new FilterDrawRepresentation();
+        return new FilterDrawRepresentation(
+                GalleryAppImpl.getContext().getString(R.string.imageDraw));
     }
 
     @Override
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
new file mode 100755
index 0000000..369e3b5
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamFusion.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015,2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+class ImageFilterDualCamFusion extends ImageFilterDualCamera {
+    private static final String TAG = ImageFilterDualCamFusion.class.getSimpleName();
+
+    public ImageFilterDualCamFusion() {
+        mSupportFusion = true;
+        mName = "Fusion";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        return new FilterDualCamFusionRepresentation();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
new file mode 100755
index 0000000..18659c4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterDualCamera.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.Log;
+import android.util.Size;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
+
+class ImageFilterDualCamera extends ImageFilter {
+    private static final String TAG = ImageFilterDualCamera.class.getSimpleName();
+
+    private FilterDualCamBasicRepresentation mParameters;
+    private Paint mPaint = new Paint();
+
+    public FilterRepresentation getDefaultRepresentation() {
+        return null;
+    }
+
+    public void useRepresentation(FilterRepresentation representation) {
+        mParameters = (FilterDualCamBasicRepresentation) representation;
+    }
+
+    boolean mSupportFusion = false;
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+        if (mParameters == null) {
+            return bitmap;
+        }
+
+        Point point = new Point(mParameters.getPoint());
+        if (!point.equals(-1, -1)) {
+            MasterImage image = MasterImage.getImage();
+
+            Size size = getFilteredSize(image, quality);
+            DualCameraEffect effect = image.getDualCameraEffect(size.getWidth(), size.getHeight());
+            if (effect == null) {
+                return bitmap;
+            }
+            size = effect.size();
+
+            Bitmap filteredBitmap = image.getBitmapCache().getBitmap(size.getWidth(),
+                    size.getHeight(), BitmapCache.FILTERS);
+            Log.d(TAG, "filtered: " + size.getWidth() + "x" + size.getHeight());
+            filteredBitmap.setHasAlpha(mSupportFusion);
+
+            float intensity = getIntensity();
+            effect.map(point);
+            int effectType = getEffectType();
+            boolean result = effect.render(effectType, point.x, point.y, filteredBitmap, intensity);
+            if (!result) {
+                showToast(R.string.dualcam_no_segment_toast, Toast.LENGTH_SHORT);
+                return bitmap;
+            }
+
+            mPaint.reset();
+            mPaint.setAntiAlias(true);
+            if (quality == FilterEnvironment.QUALITY_FINAL) {
+                mPaint.setFilterBitmap(true);
+                mPaint.setDither(true);
+            }
+
+            Canvas canvas = new Canvas(bitmap);
+            ImagePreset preset = getEnvironment().getImagePreset();
+            int bmWidth = bitmap.getWidth();
+            int bmHeight = bitmap.getHeight();
+            GeometryHolder holder;
+            if (preset.getDoApplyGeometry()) {
+                holder = GeometryMathUtils.unpackGeometry(preset.getGeometryFilters());
+            } else {
+                holder = new GeometryHolder();
+            }
+
+            RectF roiRectF = new RectF();
+            roiRectF.left = 0;
+            roiRectF.top = 0;
+            roiRectF.right = 1;
+            roiRectF.bottom = 1;
+
+            int zoomOrientation = image.getZoomOrientation();
+            if (isRotated(zoomOrientation)) {
+                Matrix mt = new Matrix();
+                mt.preRotate(GeometryMathUtils.getRotationForOrientation(zoomOrientation),
+                        0.5f, 0.5f);
+                mt.mapRect(roiRectF);
+            }
+
+            // Check for ROI cropping
+            if (!FilterCropRepresentation.getNil().equals(roiRectF)) {
+                if (FilterCropRepresentation.getNil().equals(holder.crop)) {
+                    // no crop filter, set crop to be roiRect
+                    holder.crop.set(roiRectF);
+                } else if (!roiRectF.contains(holder.crop)) {
+                    // take smaller intersecting area between roiRect and crop rect
+                    holder.crop.left = Math.max(holder.crop.left, roiRectF.left);
+                    holder.crop.top = Math.max(holder.crop.top, roiRectF.top);
+                    holder.crop.right = Math.min(holder.crop.right, roiRectF.right);
+                    holder.crop.bottom = Math.min(holder.crop.bottom, roiRectF.bottom);
+                }
+            }
+
+            RectF crop = new RectF();
+            Matrix m = GeometryMathUtils.getOriginalToScreen(holder, crop, true,
+                    size.getWidth(), size.getHeight(), bmWidth, bmHeight);
+
+            if (mSupportFusion) canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+            canvas.save();
+            canvas.clipRect(crop);
+            canvas.drawBitmap(filteredBitmap, m, mPaint);
+            canvas.restore();
+
+            image.getBitmapCache().cache(filteredBitmap);
+        }
+        return bitmap;
+    }
+
+    private int getEffectType() {
+        switch (mParameters.getTextId()) {
+            case R.string.focus: return DualCameraEffect.REFOCUS_CIRCLE;
+            case R.string.halo: return DualCameraEffect.HALO;
+            case R.string.motion: return DualCameraEffect.MOTION_BLUR;
+            case R.string.posterize: return DualCameraEffect.POSTERIZE;
+            case R.string.sketch: return DualCameraEffect.SKETCH;
+            case R.string.zoom: return DualCameraEffect.ZOOM_BLUR;
+            case R.string.bw: return DualCameraEffect.BLACK_WHITE;
+            case R.string.blackboard: return DualCameraEffect.BLACKBOARD;
+            case R.string.whiteboard: return DualCameraEffect.WHITEBOARD;
+            case R.string.fusion: return DualCameraEffect.FUSION_FOREGROUND;
+            case R.string.dc_negative: return DualCameraEffect.NEGATIVE;
+            default: throw new IllegalArgumentException();
+        }
+    }
+
+    private Size getFilteredSize(MasterImage image, int quality) {
+        int width, height;
+        if (quality == FilterEnvironment.QUALITY_FINAL) {
+            Rect originalBounds = image.getOriginalBounds();
+            width = originalBounds.width();
+            height = originalBounds.height();
+        } else {
+
+            Bitmap originalBmp = image.getOriginalBitmapHighres();
+            width = originalBmp.getWidth();
+            height = originalBmp.getHeight();
+
+            // image is rotated
+            int orientation = image.getOrientation();
+            if (isRotated(orientation)) {
+                int tmp = width;
+                width = height;
+                height = tmp;
+            }
+
+            // non even width or height
+            if (width % 2 != 0 || height % 2 != 0) {
+                float aspect = (float) height / (float) width;
+                if (width >= height) {
+                    width = MasterImage.MAX_BITMAP_DIM;
+                    height = (int) (width * aspect);
+                } else {
+                    height = MasterImage.MAX_BITMAP_DIM;
+                    width = (int) (height / aspect);
+                }
+            }
+        }
+        return new Size(width, height);
+    }
+
+    private boolean isRotated(int orientation) {
+        return orientation == ImageLoader.ORI_ROTATE_90 ||
+                orientation == ImageLoader.ORI_ROTATE_270 ||
+                orientation == ImageLoader.ORI_TRANSPOSE ||
+                orientation == ImageLoader.ORI_TRANSVERSE;
+    }
+
+    private float getIntensity() {
+        float value = (float) mParameters.getValue();
+        float max = (float) mParameters.getMaximum();
+        return max != 0 ? value / max : 0;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
index 2d0d765..12e4384 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Bitmap;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class ImageFilterEdge extends SimpleImageFilter {
     private static final String SERIALIZATION_NAME = "EDGE";
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
index 69eab73..e65cbc2 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
index 4d5a79c..aa31626 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java
@@ -20,7 +20,7 @@
 import android.graphics.Color;
 import android.graphics.Matrix;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
 
 import android.graphics.Bitmap;
@@ -33,7 +33,7 @@
 import android.renderscript.Type;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
 
 public class ImageFilterGrad extends ImageFilterRS {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
index 4c837e0..c8af46b 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Bitmap;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class ImageFilterHighlights extends SimpleImageFilter {
     private static final String SERIALIZATION_NAME = "HIGHLIGHTS";
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
index b87c254..2ca2265 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.BasicEditor;
 
 import android.graphics.Bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
index 77cdf47..0966a9f 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java
@@ -19,7 +19,7 @@
 import android.graphics.Bitmap;
 import android.text.format.Time;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class ImageFilterKMeans extends SimpleImageFilter {
     private static final String SERIALIZATION_NAME = "KMEANS";
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupBigeye.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupBigeye.java
new file mode 100644
index 0000000..ab10d6a
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupBigeye.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+import org.codeaurora.gallery.R;
+
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
+
+public class ImageFilterMakeupBigeye extends SimpleMakeupImageFilter {
+    private static final String SERIALIZATION_NAME = "BIGEYE";
+
+    public ImageFilterMakeupBigeye() {
+        mName = "Bigeye";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation =
+                (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("Bigeye");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(ImageFilterMakeupBigeye.class);
+        representation.setTextId(R.string.text_makeup_bigeye);
+        representation.setOverlayOnly(true);
+        representation.setOverlayId(R.drawable.ic_ts_makeup_bigeye);
+        representation.setMinimum(0);
+        representation.setMaximum(100);
+        representation.setSupportsPartialRendering(true);
+        return representation;
+    }
+
+    protected void doMakeupEffect(Bitmap bitmap, FaceInfo faceInfo, int width, int height,
+            int value) {
+        MakeupEngine.doWarpFace(bitmap, bitmap, width, height, faceInfo.eye1, faceInfo.eye2,
+                faceInfo.mouth, value, 0);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupSoften.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupSoften.java
new file mode 100644
index 0000000..b92ab34
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupSoften.java
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+import org.codeaurora.gallery.R;
+
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
+
+public class ImageFilterMakeupSoften extends SimpleMakeupImageFilter {
+    private static final String SERIALIZATION_NAME = "SOFTEN";
+
+    public ImageFilterMakeupSoften() {
+        mName = "Soften";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation =
+                (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("Soften");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(ImageFilterMakeupSoften.class);
+        representation.setTextId(R.string.text_makeup_Soften);
+        representation.setOverlayOnly(true);
+        representation.setOverlayId(R.drawable.ic_ts_makeup_soften);
+        representation.setMinimum(0);
+        representation.setMaximum(100);
+        representation.setSupportsPartialRendering(true);
+        return representation;
+    }
+
+    protected void doMakeupEffect(Bitmap bitmap, FaceInfo faceInfo, int width, int height, int value) {
+        MakeupEngine.doProcessBeautify(bitmap, bitmap, width, height, faceInfo.face, value, 0);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupTrimface.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupTrimface.java
new file mode 100644
index 0000000..d4a1e47
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupTrimface.java
@@ -0,0 +1,55 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+import org.codeaurora.gallery.R;
+
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
+
+public class ImageFilterMakeupTrimface extends SimpleMakeupImageFilter {
+    private static final String SERIALIZATION_NAME = "TRIMFACE";
+
+    public ImageFilterMakeupTrimface() {
+        mName = "Trimface";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation =
+                (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("Trimface");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(ImageFilterMakeupTrimface.class);
+        representation.setTextId(R.string.text_makeup_trimface);
+        representation.setOverlayOnly(true);
+        representation.setOverlayId(R.drawable.ic_ts_makeup_trimface);
+        representation.setMinimum(0);
+        representation.setMaximum(100);
+        representation.setSupportsPartialRendering(true);
+        return representation;
+    }
+
+    protected void doMakeupEffect(Bitmap bitmap, FaceInfo faceInfo, int width, int height,
+            int value) {
+        MakeupEngine.doWarpFace(bitmap, bitmap, width, height, faceInfo.eye1, faceInfo.eye2,
+                faceInfo.mouth, 0, value);
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupWhiten.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupWhiten.java
new file mode 100644
index 0000000..817a977
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterMakeupWhiten.java
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+import org.codeaurora.gallery.R;
+
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
+
+public class ImageFilterMakeupWhiten extends SimpleMakeupImageFilter {
+    private static final String SERIALIZATION_NAME = "WHITEN";
+
+    public ImageFilterMakeupWhiten() {
+        mName = "Whiten";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation =
+                (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("Whiten");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(ImageFilterMakeupWhiten.class);
+        representation.setTextId(R.string.text_makeup_whiten);
+        representation.setOverlayOnly(true);
+        representation.setOverlayId(R.drawable.ic_ts_makeup_whiten);
+        representation.setMinimum(0);
+        representation.setMaximum(100);
+        representation.setSupportsPartialRendering(true);
+        return representation;
+    }
+
+    protected void doMakeupEffect(Bitmap bitmap, FaceInfo faceInfo, int width, int height, int value) {
+        MakeupEngine.doProcessBeautify(bitmap, bitmap, width, height, faceInfo.face, 0, value);
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
index 9a1a840..88cc08f 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java
@@ -2,7 +2,7 @@
 
 import android.graphics.Bitmap;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
 public class ImageFilterNegative extends ImageFilter {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java
new file mode 100644
index 0000000..de52ee0
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterPreset.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.net.Uri;
+import com.android.gallery3d.app.Log;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.tools.FilterGeneratorNativeEngine;
+
+public class ImageFilterPreset extends ImageFilter {
+
+    private static final String LOGTAG = "ImageFilterPreset";
+    private FilterPresetRepresentation mParameters = null;
+    private Bitmap mPresetBitmap = null;
+    private Resources mResources = null;
+    private int mPresetBitmapId = 0;
+    private Uri filterImageUri;
+
+    public ImageFilterPreset() {    }
+
+    @Override
+
+    public void freeResources() {
+        if (mPresetBitmap != null) mPresetBitmap.recycle();
+        mPresetBitmap = null;
+        }
+
+    @Override
+    public FilterRepresentation getDefaultRepresentation() {
+        return null;
+    }
+
+    public void useRepresentation(FilterRepresentation representation) {
+        FilterPresetRepresentation parameters = (FilterPresetRepresentation) representation;
+        mParameters = parameters;
+    }
+
+    public FilterPresetRepresentation getParameters() {
+        return mParameters;
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+        if (getParameters() == null || mResources == null) {
+            return bitmap;
+        }
+
+        int bitmapResourceId = getParameters().getBitmapResource();
+        if (bitmapResourceId == 0) { // null filter preset
+            return bitmap;
+        }
+
+        int highresPreviewSize = Math.min(MasterImage.MAX_BITMAP_DIM, MasterImage.getImage().getActivity().getScreenImageSize());
+
+        filterImageUri = getParameters().getUri();
+        Bitmap filter = ImageLoader.loadOrientedConstrainedBitmap(filterImageUri,
+                MasterImage.getImage().getActivity(), highresPreviewSize,
+                MasterImage.getImage().getOrientation(), new Rect());
+
+        FilterGeneratorNativeEngine.getInstance().filterGeneratorProcess(bitmap,filter,bitmap);
+        return bitmap;
+    }
+
+    public void setResources(Resources resources) {
+        mResources = resources;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
index 3c54456..3a2ad91 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -21,7 +21,7 @@
 import android.renderscript.*;
 import android.util.Log;
 import android.content.res.Resources;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.pipeline.PipelineInterface;
 
 public abstract class ImageFilterRS extends ImageFilter {
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
index c3124ff..7f5d7e8 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
index bd119bb..2b30030 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
old mode 100644
new mode 100755
index bfec89f..9f6af5a
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java
@@ -16,13 +16,16 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import android.renderscript.Element;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+
 import com.android.gallery3d.filtershow.editors.BasicEditor;
+import org.codeaurora.gallery.R;
 
 public class ImageFilterSharpen extends ImageFilterRS {
     private static final String SERIALIZATION_NAME = "SHARPEN";
     private static final String LOGTAG = "ImageFilterSharpen";
-    private ScriptC_convolve3x3 mScript;
+    private ScriptIntrinsicConvolve3x3 mScript;
 
     private FilterBasicRepresentation mParameters;
 
@@ -31,12 +34,11 @@
     }
 
     public FilterRepresentation getDefaultRepresentation() {
-        FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", 0, 0, 100);
+        FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", -100, 0, 100);
         representation.setSerializationName(SERIALIZATION_NAME);
         representation.setShowParameterValue(true);
         representation.setFilterClass(ImageFilterSharpen.class);
         representation.setTextId(R.string.sharpness);
-        representation.setOverlayId(R.drawable.filtershow_button_colors_sharpen);
         representation.setEditorId(BasicEditor.ID);
         representation.setSupportsPartialRendering(true);
         return representation;
@@ -64,13 +66,13 @@
     protected void createFilter(android.content.res.Resources res, float scaleFactor,
             int quality) {
         if (mScript == null) {
-            mScript = new ScriptC_convolve3x3(getRenderScriptContext());
+            mScript = ScriptIntrinsicConvolve3x3.create(getRenderScriptContext(),
+                    Element.RGBA_8888(getRenderScriptContext()));
         }
     }
 
     private void computeKernel() {
-        float scaleFactor = getEnvironment().getScaleFactor();
-        float p1 = mParameters.getValue() * scaleFactor;
+        float p1 = mParameters.getValue();
         float value = p1 / 100.0f;
         float f[] = new float[9];
         float p = value;
@@ -83,15 +85,11 @@
         f[6] = -p;
         f[7] = -p;
         f[8] = -p;
-        mScript.set_gCoeffs(f);
+        mScript.setCoefficients(f);
     }
 
     @Override
     protected void bindScriptValues() {
-        int w = getInPixelsAllocation().getType().getX();
-        int h = getInPixelsAllocation().getType().getY();
-        mScript.set_gWidth(w);
-        mScript.set_gHeight(h);
     }
 
     @Override
@@ -100,9 +98,8 @@
             return;
         }
         computeKernel();
-        mScript.set_gIn(getInPixelsAllocation());
-        mScript.bind_gPixels(getInPixelsAllocation());
-        mScript.forEach_root(getInPixelsAllocation(), getOutPixelsAllocation());
+        mScript.setInput(getInPixelsAllocation());
+        mScript.forEach(getOutPixelsAllocation());
     }
 
 }
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortrait.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortrait.java
new file mode 100644
index 0000000..7af5f6d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortrait.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.GalleryAppImpl;
+import com.android.gallery3d.filtershow.cache.BitmapCache;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils;
+import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine.EffectType;
+
+public class ImageFilterTruePortrait extends ImageFilter {
+    private static final String TAG = "ImageFilterTruePortrait";
+
+    private FilterRepresentation mParameters;
+    private Paint mPaint = new Paint();
+
+    public void useRepresentation(FilterRepresentation representation) {
+        mParameters = representation;
+    }
+
+    public FilterRepresentation getParameters() {
+        return mParameters;
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+        if (getParameters() == null || quality == FilterEnvironment.QUALITY_ICON) {
+            return bitmap;
+        }
+
+        Bitmap filteredBitmap = null;
+        boolean result = false;
+        int orientation = MasterImage.getImage().getOrientation();
+        Rect originalBounds = MasterImage.getImage().getOriginalBounds();
+        int filteredW;
+        int filteredH;
+
+        if(quality == FilterEnvironment.QUALITY_FINAL) {
+            filteredW = originalBounds.width();
+            filteredH = originalBounds.height();
+        } else {
+            Bitmap originalBmp = MasterImage.getImage().getOriginalBitmapHighres();
+            filteredW = originalBmp.getWidth();
+            filteredH = originalBmp.getHeight();
+
+            // image is rotated
+            if (orientation == ImageLoader.ORI_ROTATE_90 ||
+                    orientation == ImageLoader.ORI_ROTATE_270 ||
+                    orientation == ImageLoader.ORI_TRANSPOSE ||
+                    orientation == ImageLoader.ORI_TRANSVERSE) {
+                int tmp = filteredW;
+                filteredW = filteredH;
+                filteredH = tmp;
+            }
+
+            // non even width or height
+            if(filteredW%2 != 0 || filteredH%2 != 0) {
+                float aspect = (float)filteredH / (float)filteredW;
+                if(filteredW >= filteredH) {
+                    filteredW = MasterImage.MAX_BITMAP_DIM;
+                    filteredH = (int)(filteredW * aspect);
+                } else {
+                    filteredH = MasterImage.MAX_BITMAP_DIM;
+                    filteredW = (int)(filteredH / aspect);
+                }
+            }
+        }
+
+        filteredBitmap = MasterImage.getImage().getBitmapCache().getBitmap(filteredW, filteredH, BitmapCache.FILTERS);
+
+        result = applyEffect(filteredBitmap);
+
+        if(result == false) {
+            Log.e(TAG, "Imagelib API failed");
+            showToast(GalleryAppImpl.getContext().getString(R.string.no_faces_found),
+                    Toast.LENGTH_SHORT);
+            return bitmap;
+        } else {
+
+            mPaint.reset();
+            mPaint.setAntiAlias(true);
+            if(quality == FilterEnvironment.QUALITY_FINAL) {
+                mPaint.setFilterBitmap(true);
+                mPaint.setDither(true);
+            }
+
+            if(needsClear()) {
+                bitmap.setHasAlpha(true);
+                bitmap.eraseColor(Color.TRANSPARENT);
+            }
+
+            Canvas canvas = new Canvas(bitmap);
+            ImagePreset preset = getEnvironment().getImagePreset();
+            int bmWidth = bitmap.getWidth();
+            int bmHeight = bitmap.getHeight();
+            GeometryHolder holder;
+            if(preset.getDoApplyGeometry()) {
+                holder = GeometryMathUtils.unpackGeometry(preset.getGeometryFilters());
+            } else {
+                holder = new GeometryHolder();
+            }
+
+            RectF crop = new RectF();
+            Matrix m = GeometryMathUtils.getOriginalToScreen(holder, crop, true,
+                    filteredW, filteredH, bmWidth, bmHeight);
+
+            canvas.save();
+            canvas.clipRect(crop);
+            canvas.drawBitmap(filteredBitmap, m, mPaint);
+            canvas.restore();
+
+            MasterImage.getImage().getBitmapCache().cache(filteredBitmap);
+        }
+
+        return bitmap;
+    }
+
+    protected boolean applyEffect(Bitmap filteredBitmap) {
+        FilterBasicRepresentation basicRep = (FilterBasicRepresentation) getParameters();
+        int value = basicRep.getValue();
+
+        boolean result = false;
+        switch(mParameters.getTextId()) {
+        case R.string.blur:
+            result = TruePortraitNativeEngine.getInstance().applyEffect(EffectType.BLUR, value, filteredBitmap);
+            break;
+        case R.string.motion_blur:
+            result = TruePortraitNativeEngine.getInstance().applyEffect(EffectType.MOTION_BLUR, value, filteredBitmap);
+            break;
+        case R.string.halo:
+            result = TruePortraitNativeEngine.getInstance().applyEffect(EffectType.HALO, value, filteredBitmap);
+            break;
+        case R.string.sketch:
+            result = TruePortraitNativeEngine.getInstance().applyEffect(EffectType.SKETCH, value, filteredBitmap);
+            break;
+        }
+
+        return result;
+    }
+
+    protected boolean needsClear() {
+        return false;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitFusion.java
new file mode 100644
index 0000000..59a15a3
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitFusion.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
+
+public class ImageFilterTruePortraitFusion extends ImageFilterTruePortrait {
+    private static final String TAG = "ImageFilterTruePortraitFusion";
+
+    public ImageFilterTruePortraitFusion() {
+        mName = "Fusion";
+    }
+
+    @Override
+    protected boolean applyEffect(Bitmap filteredBitmap) {
+        filteredBitmap.setHasAlpha(true);
+        return TruePortraitNativeEngine.getInstance().nativeGetForegroundImg(filteredBitmap);
+    }
+
+    @Override
+    protected boolean needsClear() {
+        return true;
+    }
+
+    @Override
+    public FilterRepresentation getDefaultRepresentation() {
+        return new FilterTruePortraitFusionRepresentation();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitMask.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitMask.java
new file mode 100644
index 0000000..88601c4
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterTruePortraitMask.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+
+public class ImageFilterTruePortraitMask extends ImageFilter {
+    private static final String TAG = "ImageFilterTruePortraitMask";
+
+    private FilterBasicRepresentation mParameters;
+
+    public void useRepresentation(FilterRepresentation representation) {
+        FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation;
+        mParameters = parameters;
+    }
+
+    public FilterBasicRepresentation getParameters() {
+        return mParameters;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
index 86be9a1..575bb43 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import android.graphics.Bitmap;
 
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
index 0d0dd3b..dd88f92 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java
@@ -21,7 +21,7 @@
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Rect;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.FilterEnvironment;
 import android.renderscript.Allocation;
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
index 7aa19a4..0ceaca3 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.filtershow.filters;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 
 import android.graphics.Bitmap;
diff --git a/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java b/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java
new file mode 100755
index 0000000..d72681f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SaveWaterMark.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.filtershow.filters;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.exif.ExifInterface;
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
+import com.android.gallery3d.filtershow.tools.SaveImage;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class SaveWaterMark {
+    private static final String LOGTAG = "SaveWaterMark";
+    public static final int MARK_SAVE_COMPLETE = 1;
+    private FilterWatermarkRepresentation waterMarkRp;
+    private Context mContext;
+    private static ExifInterface mExif = new ExifInterface();;
+
+    public void useRepresentation(FilterRepresentation representation) {
+        waterMarkRp = (FilterWatermarkRepresentation) representation;
+    }
+
+    public void saveImage(Context context, final Bitmap bitmap, Uri selectedUri, Handler handler,
+                          int quality, float scaleFactor, boolean isScale) {
+        mContext = context;
+        WaterMarkView mWaterMarkView = waterMarkRp.getWaterMarkView();
+        mWaterMarkView.clearEditTextCursor();
+        Bitmap markBitmap = mWaterMarkView.creatNewPhoto();
+
+        new AsyncTask<Bitmap, Void, Uri>() {
+            @Override
+            protected Uri doInBackground(Bitmap... bitmaps) {
+                ImagePreset ip = MasterImage.getImage().getPreset();
+                FilterFusionRepresentation fusionRep = findFusionRepresentation(ip);
+                boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
+                Bitmap destinationBitmap = createBitmap(bitmap, bitmaps[0]);
+                Bitmap fusionBmp = null;
+                //sampleSize is 1 for fusion bitmap of 1:1 size,
+                //sizeConstraint is 0 for fusion without width or height constraint.
+                final int sampleSize = 1, sizeConstraint = 0;
+                if (hasFusion) {
+                    fusionBmp = SaveImage.flattenFusion(mContext, Uri.parse(fusionRep.getUnderlay()), destinationBitmap,
+                            sizeConstraint, sampleSize);
+                    if(fusionBmp != null) {
+                        destinationBitmap.recycle();
+                        destinationBitmap = fusionBmp;
+                    }
+                }
+                File destinationFile = SaveImage.getNewFile(context, selectedUri);
+                //ExifInterface exif = getExifData(context, selectedUri);
+                long time = System.currentTimeMillis();
+                Uri saveUri = selectedUri;
+                if (scaleFactor != 1f) {
+                    // if we have a valid size
+                    int w = (int) (destinationBitmap.getWidth() * scaleFactor);
+                    int h = (int) (destinationBitmap.getHeight() * scaleFactor);
+                    if (w == 0 || h == 0) {
+                        w = 1;
+                        h = 1;
+                    }
+                    destinationBitmap = Bitmap.createScaledBitmap(destinationBitmap, w, h, true);
+                }
+                boolean saveHeif = destinationFile.getName().endsWith(SaveImage.POSTFIX_HEIC);
+                if (saveHeif) {
+                    if (SaveImage.putHeifData(destinationFile, mExif, destinationBitmap, quality)) {
+                        saveUri = SaveImage.linkNewFileToUri(context, selectedUri, destinationFile, time, false);
+                    }
+                } else {
+                    if (SaveImage.putExifData(destinationFile, mExif, destinationBitmap, quality)) {
+                        saveUri = SaveImage.linkNewFileToUri(context, selectedUri, destinationFile, time, false);
+                    }
+                }
+                destinationBitmap.recycle();
+                if (saveUri != selectedUri) {
+                    Log.d(GalleryActivity.QSST, "watermark saved successfully"
+                            + waterMarkRp.getSerializationName());
+                }
+                return saveUri;
+            }
+
+            @Override
+            protected void onPostExecute(Uri uri) {
+                if (isScale) return;
+                Message message = new Message();
+                message.what = MARK_SAVE_COMPLETE;
+                message.obj = uri;
+                handler.sendMessage(message);
+            }
+        }.execute(markBitmap);
+    }
+
+    public void saveImage(Context context, Bitmap bitmap, Uri selectedUri, Handler handler) {
+        saveImage(context, bitmap, selectedUri, handler, 90, 1f, false);
+
+    }
+
+    public void exportImage(Context context, Bitmap bitmap, Uri selectedUri, int quality, float scaleFactor) {
+        saveImage(context, bitmap, selectedUri, null, quality, scaleFactor, true);
+    }
+
+    private Bitmap createBitmap(Bitmap src, Bitmap watermark) {
+        if (src == null) {
+            return null;
+        }
+        Rect r = MasterImage.getImage().getImageBounds();
+        int rw = r.width();
+        int rh = r.height();
+        Bitmap resizeSrc = Bitmap.createScaledBitmap(src,rw, rh,false);
+        //create the new blank bitmap
+        Bitmap newb = Bitmap.createBitmap(rw, rh, Bitmap.Config.ARGB_8888);
+        Canvas cv = new Canvas(newb);
+        //draw src into
+        cv.drawBitmap(resizeSrc, 0, 0, null);
+        //draw watermark into
+        cv.drawBitmap(watermark, 0, 0, null);
+        //save all clip
+        cv.save();
+        //store
+        cv.restore();
+        watermark.recycle();
+        resizeSrc.recycle();
+        return newb;
+    }
+
+    private FilterFusionRepresentation findFusionRepresentation(ImagePreset preset) {
+        FilterDualCamFusionRepresentation dcRepresentation =
+                (FilterDualCamFusionRepresentation)preset.getFilterWithSerializationName(
+                        FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+        FilterTruePortraitFusionRepresentation tpRepresentation =
+                (FilterTruePortraitFusionRepresentation)preset.getFilterWithSerializationName(
+                        FilterTruePortraitFusionRepresentation.SERIALIZATION_NAME);
+
+        FilterFusionRepresentation fusionRep = null;
+
+        if(dcRepresentation != null)
+            fusionRep = (FilterFusionRepresentation) dcRepresentation;
+        else if (tpRepresentation != null)
+            fusionRep = (FilterFusionRepresentation) tpRepresentation;
+
+        return fusionRep;
+    }
+
+    public void getExifData(Context context, Uri source) {
+        //mExif = new ExifInterface();
+        String mimeType = context.getContentResolver().getType(source);
+        if (mimeType == null) {
+            mimeType = ImageLoader.getMimeType(source);
+        }
+        if (ImageLoader.JPEG_MIME_TYPE.equals(mimeType)) {
+            InputStream inStream = null;
+            try {
+                inStream = context.getContentResolver().openInputStream(source);
+                mExif.readExif(inStream);
+            } catch (FileNotFoundException e) {
+                Log.w(LOGTAG, "Cannot find file: " + source, e);
+            } catch (IOException e) {
+                Log.w(LOGTAG, "Cannot read exif for: " + source, e);
+            } catch (NullPointerException e) {
+                Log.w(LOGTAG, "Invalid exif data for: " + source, e);
+            } finally {
+                Utils.closeSilently(inStream);
+            }
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/SeeStraightActs.java b/src/com/android/gallery3d/filtershow/filters/SeeStraightActs.java
new file mode 100755
index 0000000..f2eb81b
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SeeStraightActs.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.editors.SeeStraightEditor;
+
+public class SeeStraightActs extends SimpleImageFilter {
+    public static final String SERIALIZATION_NAME = "SeeStraightActs";
+    private static final int MIN_WIDTH = 512;
+    private static final int MIN_HEIGHT = 512;
+    private static final int MIN_WIDTH_REQUIREMENT = 640;
+    private static final int MIN_HEIGHT_REQUIREMENT = 480;
+    private static final boolean DEBUG = true;
+    private static boolean isSeeStraightEnabled = true;
+
+    private void printDebug(String str) {
+        if(DEBUG)
+            android.util.Log.d("SeeStraight", str);
+    }
+
+    public static boolean isSeeStraightEnabled() {
+        return isSeeStraightEnabled;
+    }
+
+    public SeeStraightActs() {
+        mName = "SeeStraightActs";
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("SeeStraight");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(SeeStraightActs.class);
+        representation.setTextId(R.string.seestraight_acts);
+        representation.setMinimum(0);
+        representation.setMaximum(10);
+        representation.setValue(0);
+        representation.setDefaultValue(0);
+        representation.setSupportsPartialRendering(false);
+        representation.setEditorId(SeeStraightEditor.ID);
+
+        return representation;
+    }
+
+    private native int[] processImage(int width, int height, Bitmap srcBitmap, Bitmap dstBitmap);
+
+    private boolean checkSize(int w, int h) {
+        int t;
+        if(w < h) {
+            t = w;
+            w = h;
+            h = t;
+        }
+        if(w >= MIN_WIDTH_REQUIREMENT && h >= MIN_HEIGHT_REQUIREMENT) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float not_use, int quality) {
+        if(bitmap == null)
+            return null;
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+
+        if(width <= MIN_WIDTH && height <= MIN_HEIGHT)
+            return bitmap;
+
+        if(!checkSize(width, height)) {
+            showToast(R.string.seestraight_input_image_is_small, Toast.LENGTH_SHORT);
+            return bitmap;
+        }
+
+        Bitmap dstBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        int[] outputRoi = processImage(width, height, bitmap, dstBitmap);
+        if(outputRoi == null) {
+            showToast(R.string.seestraight_process_fail, Toast.LENGTH_SHORT);
+            return bitmap;
+        }
+        dstBitmap = Bitmap.createBitmap(dstBitmap, outputRoi[0], outputRoi[1], outputRoi[2], outputRoi[3]);
+        return dstBitmap;
+    }
+
+    static {
+        try {
+            System.loadLibrary("jni_seestraight");
+            isSeeStraightEnabled = true;
+        } catch(UnsatisfiedLinkError e) {
+            isSeeStraightEnabled = false;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/SimpleMakeupImageFilter.java b/src/com/android/gallery3d/filtershow/filters/SimpleMakeupImageFilter.java
new file mode 100644
index 0000000..00cf510
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/SimpleMakeupImageFilter.java
@@ -0,0 +1,87 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+import com.android.gallery3d.common.ApiHelper.SystemProperties;
+import com.thundersoft.hz.selfportrait.detect.FaceDetect;
+import com.thundersoft.hz.selfportrait.detect.FaceInfo;
+import com.thundersoft.hz.selfportrait.makeup.engine.MakeupEngine;
+
+public abstract class SimpleMakeupImageFilter extends SimpleImageFilter {
+    private static final String LOGTAG = "SimpleMakeupImageFilter";
+    protected static final int MAKEUP_INTENSITY = 50;
+
+    public static final boolean HAS_TS_MAKEUP = MakeupEngine.getMakeupObj().isLibLoaded();
+
+    public SimpleMakeupImageFilter() {
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterRepresentation representation = new FilterBasicRepresentation("Default", 0,
+                MAKEUP_INTENSITY, 100);
+        representation.setShowParameterValue(true);
+        return representation;
+    }
+
+    protected FaceInfo detectFaceInfo(Bitmap bitmap) {
+        FaceDetect faceDetect = new FaceDetect();
+        FaceInfo[] faceInfos = null;
+        if (faceDetect.isLibLoaded()) {
+            faceDetect.initialize();
+            faceInfos = faceDetect.dectectFeatures(bitmap);
+            faceDetect.uninitialize();
+        }
+
+        Log.v(LOGTAG, "SimpleMakeupImageFilter.detectFaceInfo(): detect faceNum is "
+                + (faceInfos != null ? faceInfos.length : "NULL"));
+        if (faceInfos == null || faceInfos.length <= 0) {
+            return null;
+        }
+
+        return faceInfos[0];
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) {
+        if (getParameters() == null) {
+            return bitmap;
+        }
+        int w = bitmap.getWidth();
+        int h = bitmap.getHeight();
+        if(w % 2 != 0 || h % 2 != 0) {
+            return bitmap;
+        }
+        int value = getParameters().getValue();
+        applyHelper(bitmap, w, h, value);
+        return bitmap;
+    }
+
+    private void applyHelper(Bitmap bitmap, int w, int h, int value) {
+        FaceInfo faceInfo = detectFaceInfo(bitmap);
+        if(faceInfo != null) {
+            doMakeupEffect(bitmap, faceInfo, w, h, value);
+        }
+    }
+
+    abstract void doMakeupEffect(Bitmap bitmap, FaceInfo faceInfo, int width, int height,
+            int value);
+
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java b/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java
new file mode 100755
index 0000000..6260502
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/TrueScannerActs.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.app.ProgressDialog;
+import android.graphics.Bitmap;
+import android.util.Log;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.controller.Parameter;
+import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+import com.android.gallery3d.filtershow.imageshow.ImageTrueScanner;
+import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.ui.MenuExecutor;
+import static com.android.gallery3d.filtershow.imageshow.ImageTrueScanner.*;
+
+public class TrueScannerActs extends SimpleImageFilter {
+    public static final String SERIALIZATION_NAME = "TrueScannerActs";
+    //The minimum resolution that TrueScanner library supports is VGA, i.e. 640x480.
+    public static final int MIN_WIDTH = 640;
+    public static final int MIN_HEIGHT = 480;
+    private static boolean rotating = false;
+    private static final boolean DEBUG = false;
+    private static boolean isTrueScannerEnabled = true;
+    private static boolean isPointsAcquired;
+    private final static int POINTS_LEN = 8;
+    private static int[] mAcquiredPoints = new int[POINTS_LEN+2];
+    protected boolean isWhiteBoard = false;
+    private boolean mLocked = false;
+    private Bitmap rectifiedImage = null;
+    private int[] oldPts = new int[POINTS_LEN];
+    private ProgressDialog mProgressDialog;
+
+    private void printDebug(String str) {
+        if(DEBUG)
+            android.util.Log.d("TrueScanner", str);
+    }
+
+    public static boolean isTrueScannerEnabled() {
+        return isTrueScannerEnabled;
+    }
+
+    public static boolean setRotating(boolean isRotating) {
+        return rotating = isRotating;
+    }
+
+    public TrueScannerActs() {
+        mName = "TrueScannerActs";
+        isPointsAcquired = false;
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("TrueScanner");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(TrueScannerActs.class);
+        representation.setTextId(R.string.truescanner_normal);
+        representation.setMinimum(0);
+        representation.setMaximum(10);
+        representation.setValue(0);
+        representation.setDefaultValue(0);
+        representation.setSupportsPartialRendering(false);
+        representation.setEditorId(TrueScannerEditor.ID);
+
+        return representation;
+    }
+
+    private native int[] processImage(Bitmap orgBitmap, Bitmap rectifiedBitmap, int[] cornerPts);
+    private native int enhanceImage(Bitmap orgBitmap, Bitmap rectifiedBitmap);
+
+    private synchronized boolean acquireLock(boolean isAcquiring) {
+        if(mLocked != isAcquiring) {
+            mLocked = isAcquiring;
+            return true;
+        }
+        return false;
+    }
+
+    private void showProgressDialog() {
+        if (null != sActivity) {
+            sActivity.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (!sActivity.isFinishing()) {
+                        mProgressDialog = ProgressDialog.show(sActivity,
+                                "", "Processing...", true, false);
+                        mProgressDialog.show();
+                    }
+                }
+            });
+        }
+    }
+
+    private void dismissProgressDialog() {
+        if (null != sActivity) {
+            sActivity.runOnUiThread(new Runnable() {
+                public void run() {
+                    if (mProgressDialog != null && mProgressDialog.isShowing()) {
+                        mProgressDialog.dismiss();
+                        mProgressDialog = null;
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float not_use, int quality) {
+        if(bitmap == null)
+            return null;
+        int w = bitmap.getWidth();
+        int h = bitmap.getHeight();
+        if (w < h) {
+            w = h;
+            h = bitmap.getWidth();
+        }
+        if(w <= MIN_WIDTH || h <= MIN_HEIGHT)
+            return bitmap;
+        if(ImageTrueScanner.getCordsUIState()) {
+            return bitmap;
+        }
+        if(!acquireLock(true)) {
+            showToast("Still processing the previous request... ", Toast.LENGTH_LONG);
+            return bitmap;
+        }
+        new Throwable().printStackTrace();
+        int[] pts = ImageTrueScanner.getDeterminedPoints();
+        int[] resultPts = new int[POINTS_LEN];
+        float xScale = ((float)bitmap.getWidth())/pts[POINTS_LEN];
+        float yScale = ((float)bitmap.getHeight())/pts[POINTS_LEN+1];
+        for(int i=0; i < POINTS_LEN; i++) {
+            if(i%2 == 0)
+                resultPts[i] = (int)((pts[i] - pts[POINTS_LEN+2])*xScale);
+            else
+                resultPts[i] = (int)((pts[i] - pts[POINTS_LEN+3])*yScale);
+        }
+        if (rotating && rectifiedImage != null) {
+            acquireLock(false);
+            rotating = false;
+            return rectifiedImage;
+        }
+        rectifiedImage = Bitmap.createBitmap(
+                bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
+        int[] outputSize = processImage(bitmap, rectifiedImage, resultPts);
+        rectifiedImage = Bitmap.createBitmap(
+                rectifiedImage, 0, 0, outputSize[0], outputSize[1]);
+        if(ImageTrueScanner.getRemoveGlareButtonStatus()) {
+            Bitmap enhancedImage = Bitmap.createBitmap(
+                    outputSize[0], outputSize[1], Bitmap.Config.ARGB_8888);
+            showProgressDialog();
+            enhanceImage(rectifiedImage, enhancedImage);
+            dismissProgressDialog();
+            rectifiedImage = enhancedImage;
+        }
+        acquireLock(false);
+
+        return rectifiedImage;
+    }
+
+    static {
+        try {
+            System.loadLibrary("jni_truescanner_v2");
+            isTrueScannerEnabled = true;
+        } catch(UnsatisfiedLinkError e) {
+            isTrueScannerEnabled = false;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/TrueScannerWhiteBoardActs.java b/src/com/android/gallery3d/filtershow/filters/TrueScannerWhiteBoardActs.java
new file mode 100644
index 0000000..a403c24
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/filters/TrueScannerWhiteBoardActs.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.filters;
+
+import android.graphics.Bitmap;
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+
+public class TrueScannerWhiteBoardActs extends TrueScannerActs {
+    public static final String SERIALIZATION_NAME = "TrueScannerWhiteBoardActs";
+
+    public TrueScannerWhiteBoardActs() {
+        super();
+        isWhiteBoard = true;
+    }
+
+    public FilterRepresentation getDefaultRepresentation() {
+        FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation();
+        representation.setName("TrueScannerWhiteBoard");
+        representation.setSerializationName(SERIALIZATION_NAME);
+        representation.setFilterClass(TrueScannerWhiteBoardActs.class);
+        representation.setTextId(R.string.truescanner_white);
+        representation.setMinimum(0);
+        representation.setMaximum(10);
+        representation.setValue(0);
+        representation.setDefaultValue(0);
+        representation.setSupportsPartialRendering(false);
+        representation.setEditorId(TrueScannerEditor.ID);
+
+        return representation;
+    }
+
+    @Override
+    public Bitmap apply(Bitmap bitmap, float not_use, int quality) {
+        return super.apply(bitmap, not_use, quality);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
index 2acffab..d348b92 100644
--- a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
+++ b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs
@@ -31,15 +31,15 @@
     uint32_t y1 = min((int32_t)y+1, gHeight-1);
     uint32_t y2 = max((int32_t)y-1, 0);
 
-    float4 p00 = rsUnpackColor8888(gPixels[x1 + gWidth * y1]);
-    float4 p01 = rsUnpackColor8888(gPixels[x + gWidth * y1]);
-    float4 p02 = rsUnpackColor8888(gPixels[x2 + gWidth * y1]);
-    float4 p10 = rsUnpackColor8888(gPixels[x1 + gWidth * y]);
-    float4 p11 = rsUnpackColor8888(gPixels[x + gWidth * y]);
-    float4 p12 = rsUnpackColor8888(gPixels[x2 + gWidth * y]);
-    float4 p20 = rsUnpackColor8888(gPixels[x1 + gWidth * y2]);
-    float4 p21 = rsUnpackColor8888(gPixels[x + gWidth * y2]);
-    float4 p22 = rsUnpackColor8888(gPixels[x2 + gWidth * y2]);
+    float4 p00 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x1, y1)));
+    float4 p01 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x, y1)));
+    float4 p02 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x2, y1)));
+    float4 p10 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x1, y)));
+    float4 p11 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x, y)));
+    float4 p12 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x2, y)));
+    float4 p20 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x1, y2)));
+    float4 p21 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x, y2)));
+    float4 p22 = rsUnpackColor8888(*((uchar4 *)rsGetElementAt(gIn, x2, y2)));
 
     p00 *= gCoeffs[0];
     p01 *= gCoeffs[1];
diff --git a/src/com/android/gallery3d/filtershow/history/HistoryManager.java b/src/com/android/gallery3d/filtershow/history/HistoryManager.java
index 569b299..216bb1e 100644
--- a/src/com/android/gallery3d/filtershow/history/HistoryManager.java
+++ b/src/com/android/gallery3d/filtershow/history/HistoryManager.java
@@ -25,10 +25,13 @@
     private static final String LOGTAG = "HistoryManager";
 
     private Vector<HistoryItem> mHistoryItems = new Vector<HistoryItem>();
+    private Vector<HistoryItem> mHistoryItemsActiveFilter = new Vector<HistoryItem>();
     private int mCurrentPresetPosition = 0;
+    private int mComparePresetPosition = 0;
     private MenuItem mUndoMenuItem = null;
     private MenuItem mRedoMenuItem = null;
     private MenuItem mResetMenuItem = null;
+    private int mActiveFilter = -1;
 
     public void setMenuItems(MenuItem undoItem, MenuItem redoItem, MenuItem resetItem) {
         mUndoMenuItem = undoItem;
@@ -68,7 +71,7 @@
     }
 
     public boolean canUndo() {
-        if (mCurrentPresetPosition == getCount() - 1) {
+        if (mCurrentPresetPosition >= getCount() - 1) {
             return false;
         }
         return true;
@@ -128,6 +131,7 @@
 
     public void addHistoryItem(HistoryItem preset) {
         insert(preset, 0);
+        insertActiveFilter(preset, 0);
         updateMenuItems();
     }
 
@@ -170,4 +174,46 @@
         return mCurrentPresetPosition;
     }
 
+    public int backToOriginal() {
+        saveComparePresetPosition();
+            mCurrentPresetPosition = getCount() - 1;
+        return mCurrentPresetPosition;
+    }
+
+    public int backToCurrent() {
+        mCurrentPresetPosition = getCurrentPresetPosition();
+        return mCurrentPresetPosition;
+    }
+    public int setActiveFilter(int value)
+    {
+        mActiveFilter = value;
+        return mActiveFilter;
+    }
+    private void insertActiveFilter(HistoryItem preset, int position)
+    {
+        mHistoryItemsActiveFilter.add(preset);
+    }
+    public void resetActiveFilter()
+    {
+        mHistoryItemsActiveFilter.clear();
+    }
+    public int undoCurrentFilter()
+    {
+        mCurrentPresetPosition = mCurrentPresetPosition + mHistoryItemsActiveFilter.size();
+        if (mCurrentPresetPosition >= getCount()) {
+            mCurrentPresetPosition = getCount() - 1;
+        }
+        updateMenuItems();
+        return mCurrentPresetPosition;
+    }
+
+    public void saveComparePresetPosition()
+    {
+        mComparePresetPosition = mCurrentPresetPosition ;
+    }
+    public int getCurrentPresetPosition()
+    {
+        return mComparePresetPosition;
+    }
+
 }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
index 06fc1dc..b67da46 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java
@@ -27,7 +27,7 @@
 import android.graphics.Shader;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class EclipseControl {
     private float mCenterX = Float.NaN;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
old mode 100644
new mode 100755
index 614b648..3b2a704
--- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -237,7 +238,7 @@
         }
     }
 
-    private static int getRotationForOrientation(int orientation) {
+    public static int getRotationForOrientation(int orientation) {
         switch (orientation) {
             case ImageLoader.ORI_ROTATE_90:
                 return 90;
@@ -319,6 +320,7 @@
         BitmapCache bitmapCache = MasterImage.getImage().getBitmapCache();
         Bitmap temp = bitmapCache.getBitmap(frame.width(),
                 frame.height(), BitmapCache.UTIL_GEOMETRY);
+        temp.eraseColor(Color.TRANSPARENT);
         Canvas canvas = new Canvas(temp);
         Paint paint = new Paint();
         paint.setAntiAlias(true);
@@ -370,16 +372,41 @@
     }
 
     public static Matrix getOriginalToScreen(GeometryHolder holder, boolean rotate,
-            float originalWidth,
-            float originalHeight, float viewWidth, float viewHeight) {
+            float originalWidth, float originalHeight, float viewWidth, float viewHeight) {
+        return getOriginalToScreen(holder, null, rotate, originalWidth, originalHeight, viewWidth, viewHeight);
+    }
+
+    public static Matrix getOriginalToScreen(GeometryHolder holder, RectF outCrop,
+            boolean rotate, float originalWidth, float originalHeight,
+            float viewWidth, float viewHeight) {
+        RectF crop = new RectF();
+        Matrix m;
         int orientation = MasterImage.getImage().getZoomOrientation();
-        int rotation = getRotationForOrientation(orientation);
-        Rotation prev = holder.rotation;
-        rotation = (rotation + prev.value()) % 360;
-        holder.rotation = Rotation.fromValue(rotation);
-        Matrix m = getCropSelectionToScreenMatrix(null, holder, (int) originalWidth,
-                (int) originalHeight, (int) viewWidth, (int) viewHeight);
-        holder.rotation = prev;
+
+        if (orientation == ImageLoader.ORI_ROTATE_90 ||
+                orientation == ImageLoader.ORI_ROTATE_270 ||
+                orientation == ImageLoader.ORI_TRANSPOSE ||
+                orientation == ImageLoader.ORI_TRANSVERSE) {
+
+            crop = getTrueCropRect(holder, (int)originalHeight, (int)originalWidth);
+        } else {
+            crop = getTrueCropRect(holder, (int)originalWidth, (int)originalHeight);
+        }
+
+        float scale = scale(crop.width(), crop.height(), viewWidth, viewHeight);
+
+        m = getFullGeometryMatrix(holder, (int)originalWidth, (int)originalHeight);
+        if(orientation != ImageLoader.ORI_NORMAL) {
+            addOrientationToMatrix(m, (int)originalWidth, (int)originalHeight, orientation);
+        }
+
+        m.postScale(scale, scale);
+        GeometryMathUtils.scaleRect(crop, scale);
+        m.postTranslate(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY());
+        crop.offset(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY());
+        if(outCrop != null) {
+            outCrop.set(crop);
+        }
         return m;
     }
 
@@ -426,7 +453,7 @@
     }
 
     // Gives matrix for rotated, straightened, mirrored bitmap centered at 0,0.
-    private static Matrix getFullGeometryMatrix(GeometryHolder holder, int bitmapWidth,
+    public static Matrix getFullGeometryMatrix(GeometryHolder holder, int bitmapWidth,
             int bitmapHeight) {
         float centerX = bitmapWidth / 2f;
         float centerY = bitmapHeight / 2f;
@@ -446,6 +473,9 @@
             bw = bitmapHeight;
         }
         float scale = GeometryMathUtils.scale(bw, bh, viewWidth, viewHeight);
+        if (scale > 3.0f) {
+            scale = 3.0f;
+        }
         scale *= SHOW_SCALE;
         float s = Math.min(viewWidth / (float) bitmapWidth, viewHeight / (float) bitmapHeight);
         Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight);
@@ -454,6 +484,71 @@
         return m;
     }
 
+    public static Matrix getSegMatrix(GeometryHolder holder, int bitmapWidth,
+                                      int bitmapHeight, int viewWidth, int viewHeight
+            , int oldw, int oldh) {
+        int bh = bitmapHeight;
+        int bw = bitmapWidth;
+        if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) {
+            bh = bitmapWidth;
+            bw = bitmapHeight;
+        }
+        float oldScale = GeometryMathUtils.scale(bw, bh, oldw, oldh);
+        if (oldScale > 3.0f) {
+            oldScale = 3.0f;
+        }
+        oldScale *= SHOW_SCALE;
+        float scale = GeometryMathUtils.scale(bw, bh, viewWidth, viewHeight);
+        if (scale > 3.0f) {
+            scale = 3.0f;
+        }
+        scale *= SHOW_SCALE;
+        Matrix m = new Matrix();
+        m.setTranslate(-oldw / 2f, -oldh / 2f);
+        m.postScale(scale / oldScale, scale / oldScale);
+        m.postTranslate(viewWidth / 2f, viewHeight / 2f);
+        return m;
+    }
+
+    public static Matrix getWatermarkMatrix(GeometryHolder holder, int bitmapWidth,
+                                            int bitmapHeight, int viewWidth, int viewHeight
+            , int oldw, int oldh) {
+        int bh = bitmapHeight;
+        int bw = bitmapWidth;
+        if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) {
+            bh = bitmapWidth;
+            bw = bitmapHeight;
+        }
+        float scale = GeometryMathUtils.getWatermarkScale(holder,bw, bh, viewWidth, viewHeight, oldw, oldh);
+        Matrix m = new Matrix();
+        m.setTranslate(-oldw / 2f, -oldh / 2f);
+        m.postScale(scale, scale);
+        m.postTranslate(viewWidth / 2f, viewHeight / 2f);
+        return m;
+    }
+
+    public static float getWatermarkScale(GeometryHolder holder, int bitmapWidth,
+                                          int bitmapHeight, int viewWidth, int viewHeight,
+                                          int oldw, int oldh) {
+        int bh = bitmapHeight;
+        int bw = bitmapWidth;
+        if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) {
+            bh = bitmapWidth;
+            bw = bitmapHeight;
+        }
+        float oldScale = GeometryMathUtils.scale(bw, bh, oldw, oldh);
+        if (oldScale > 3.0f) {
+            oldScale = 3.0f;
+        }
+        oldScale *= SHOW_SCALE;
+        float scale = GeometryMathUtils.scale(bw, bh, viewWidth, viewHeight);
+        if (scale > 3.0f) {
+            scale = 3.0f;
+        }
+        scale *= SHOW_SCALE;
+        return scale / oldScale;
+    }
+
     public static RectF getTrueCropRect(GeometryHolder holder, int bitmapWidth, int bitmapHeight) {
         RectF r = new RectF(holder.crop);
         FilterCropRepresentation.findScaledCrop(r, bitmapWidth, bitmapHeight);
@@ -487,4 +582,32 @@
         return getCropSelectionToScreenMatrix(outCrop, holder, bitmapWidth, bitmapHeight,
                 viewWidth, viewHeight);
     }
+
+    public static void addOrientationToMatrix(Matrix matrix, int w, int h, int orientation) {
+        switch (orientation) {
+            case ImageLoader.ORI_ROTATE_90:
+                matrix.preRotate(90, w/2, h/2);
+                break;
+            case ImageLoader.ORI_ROTATE_180:
+                matrix.preRotate(180, w/2, h/2);
+                break;
+            case ImageLoader.ORI_ROTATE_270:
+                matrix.preRotate(270, w/2, h/2);
+                break;
+            case ImageLoader.ORI_FLIP_HOR:
+                matrix.preScale(-1, 1);
+                break;
+            case ImageLoader.ORI_FLIP_VERT:
+                matrix.preScale(1, -1);
+                break;
+            case ImageLoader.ORI_TRANSPOSE:
+                matrix.preScale(1, -1);
+                matrix.preRotate(90, w / 2f, h / 2f);
+                break;
+            case ImageLoader.ORI_TRANSVERSE:
+                matrix.preScale(1, -1);
+                matrix.preRotate(270, w / 2f, h / 2f);
+                break;
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
index 2987015..4b1ab7b 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java
@@ -27,7 +27,7 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class GradControl {
     private float mPoint1X = Float.NaN; // used to flag parameters have not been set
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
index 4e53f82..baabbad 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
@@ -28,13 +28,14 @@
 import android.util.Log;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.crop.CropDrawingUtils;
 import com.android.gallery3d.filtershow.crop.CropMath;
 import com.android.gallery3d.filtershow.crop.CropObject;
 import com.android.gallery3d.filtershow.editors.EditorCrop;
 import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
 import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder;
+import org.codeaurora.gallery.R;
 
 public class ImageCrop extends ImageShow {
     private static final String TAG = ImageCrop.class.getSimpleName();
@@ -60,7 +61,6 @@
     private Mode mState = Mode.NONE;
     private boolean mValidDraw = false;
     FilterCropRepresentation mLocalRep = new FilterCropRepresentation();
-    EditorCrop mEditorCrop;
 
     public ImageCrop(Context context) {
         super(context);
@@ -188,6 +188,8 @@
             x = y;
             y = tmp;
         }
+        RectF outer = mCropObj.getOuterBounds();
+        mCropObj.resetBoundsTo(outer, outer);
         if (!mCropObj.setInnerAspectRatio(x, y)) {
             Log.w(TAG, "failed to set aspect ratio");
         }
@@ -230,9 +232,11 @@
     private void forceStateConsistency() {
         MasterImage master = MasterImage.getImage();
         Bitmap image = master.getFiltersOnlyImage();
+        FilterShowActivity filterShowActivity = (FilterShowActivity) getContext();
+        boolean isReload = filterShowActivity.isReloadByConfigurationChanged();
         int width = image.getWidth();
         int height = image.getHeight();
-        if (mCropObj == null || !mUpdateHolder.equals(mGeometry)
+        if (mCropObj == null || (!mUpdateHolder.equals(mGeometry) && !isReload)
                 || mImageBounds.width() != width || mImageBounds.height() != height
                 || !mLocalRep.getCrop().equals(mUpdateHolder.crop)) {
             mImageBounds.set(0, 0, width, height);
@@ -249,7 +253,12 @@
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
-        clearDisplay();
+        FilterShowActivity filterShowActivity = (FilterShowActivity) getContext();
+        if (filterShowActivity.isShowEditCropPanel()) {
+            updateMatrix(w, h);
+        } else {
+            clearDisplay();
+        }
     }
 
     @Override
@@ -261,17 +270,28 @@
         if (!mValidDraw || bitmap == null) {
             return;
         }
+        toggleComparisonButtonVisibility();
         forceStateConsistency();
         mImageBounds.set(0, 0, bitmap.getWidth(), bitmap.getHeight());
         // If display matrix doesn't exist, create it and its dependencies
         if (mDisplayCropMatrix == null || mDisplayMatrix == null || mDisplayMatrixInverse == null) {
             mCropObj.unsetAspectRatio();
+            Resources res = getContext().getResources();
+            int panelHeight = 0;
+            if (canvas.getWidth() < canvas.getHeight()) {
+                panelHeight = res.getDimensionPixelOffset(R.dimen.category_panel_height) +
+                        res.getDimensionPixelOffset(R.dimen.category_actionbar_panel_height);
+            } else {
+                panelHeight = res.getDimensionPixelOffset(R.dimen.crop_panel_height_lanscape);
+            }
             mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
-                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
+                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(),
+                    canvas.getHeight() - panelHeight);
             float straighten = mGeometry.straighten;
             mGeometry.straighten = 0;
             mDisplayCropMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
-                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
+                    bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(),
+                    canvas.getHeight() - panelHeight);
             mGeometry.straighten = straighten;
             mDisplayMatrixInverse = new Matrix();
             mDisplayMatrixInverse.reset();
@@ -289,8 +309,8 @@
                     CropObject.MOVE_LEFT,
                     CropObject.MOVE_RIGHT};
             int delta = Math.min(canvas.getWidth(), canvas.getHeight()) / 4;
-            int[] dy = {delta, -delta, 0, 0};
-            int[] dx = {0, 0, delta, -delta};
+            int[] dx = {delta, -delta, 0, 0};
+            int[] dy = {0, 0, delta, -delta};
 
             for (int i = 0; i < sides.length; i++) {
                 mCropObj.selectEdge(sides[i]);
@@ -311,18 +331,38 @@
                 (int) outer.height());
         FilterCropRepresentation.findScaledCrop(mScreenCropBounds, bitmap.getWidth(),
                 bitmap.getHeight());
-        if (mDisplayCropMatrix.mapRect(mScreenCropBounds)) {
-            // Draw crop rect and markers
-            CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds);
-            CropDrawingUtils.drawShade(canvas, mScreenCropBounds);
-            CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds);
-            CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize,
-                    mScreenCropBounds, mCropObj.isFixedAspect(),
-                    decode(mCropObj.getSelectState(), mGeometry.rotation.value()));
-        }
+        mDisplayCropMatrix.mapRect(mScreenCropBounds);
+        CropDrawingUtils.drawShade(canvas, mScreenCropBounds);
+        CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds, getContext());
+        CropDrawingUtils.drawCorner(canvas, mScreenCropBounds, getContext());
+        CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds, getContext());
     }
 
-    public void setEditor(EditorCrop editorCrop) {
-        mEditorCrop = editorCrop;
+    private void updateMatrix(int w, int h) {
+        Bitmap bitmap = MasterImage.getImage().getFiltersOnlyImage();
+        if (bitmap == null) {
+            MasterImage.getImage().invalidateFiltersOnly();
+        }
+        if (!mValidDraw || bitmap == null) {
+            return;
+        }
+        Resources res = getContext().getResources();
+        int panelHeight = 0;
+        if (w < h) {
+            panelHeight = res.getDimensionPixelOffset(R.dimen.category_panel_height) +
+                    res.getDimensionPixelOffset(R.dimen.category_actionbar_panel_height);
+        } else {
+            panelHeight = res.getDimensionPixelOffset(R.dimen.crop_panel_height_lanscape);
+        }
+        mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
+                bitmap.getWidth(), bitmap.getHeight(), w, h - panelHeight);
+        mDisplayCropMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
+                bitmap.getWidth(), bitmap.getHeight(), w, h - panelHeight);
+        mDisplayMatrixInverse = new Matrix();
+        mDisplayMatrixInverse.reset();
+        if (!mDisplayCropMatrix.invert(mDisplayMatrixInverse)) {
+            Log.w(TAG, "could not invert display matrix");
+            mDisplayMatrixInverse = null;
+        }
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java
index 3fb75c6..11964df 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java
@@ -33,7 +33,7 @@
 import android.widget.LinearLayout;
 import android.widget.PopupMenu;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.editors.Editor;
 import com.android.gallery3d.filtershow.editors.EditorCurves;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
index 795a247..e128069 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
@@ -20,7 +20,7 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorDraw;
 import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation;
 import com.android.gallery3d.filtershow.filters.ImageFilterDraw;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
new file mode 100644
index 0000000..1c506fd
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDualCamera.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.filtershow.editors.Editor;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+
+public class ImageDualCamera extends ImageShow {
+    private static final String LOGTAG = "ImageDualCamera";
+    protected Editor mEditor;
+    protected FilterDualCamBasicRepresentation mRepresentation;
+    private Matrix mToOrig;
+    private float[] mTmpPoint = new float[2];
+
+    public ImageDualCamera(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public ImageDualCamera(Context context) {
+        super(context);
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(MotionEvent event) {
+        Log.e(LOGTAG, "single tap: " + event.getX() + "x" + event.getY());
+        calcScreenMapping();
+        mTmpPoint[0] = event.getX();
+        mTmpPoint[1] = event.getY();
+        mToOrig.mapPoints(mTmpPoint);
+
+        mRepresentation.setPoint((int)mTmpPoint[0], (int)mTmpPoint[1]);
+        mEditor.commitLocalRepresentation();
+        return true;
+    }
+
+    public void setEditor(Editor editor) {
+        mEditor = editor;
+    }
+
+    public void setRepresentation(FilterDualCamBasicRepresentation representation) {
+        mRepresentation = representation;
+    }
+
+    private void calcScreenMapping() {
+        mToOrig = MasterImage.getImage().getScreenToImageMatrix(true);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java b/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java
new file mode 100644
index 0000000..6d4ef9f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageFusion.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.editors.EditorDualCamFusion;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+
+public class ImageFusion extends ImageShow {
+    private static final String LOGTAG = "ImageFusion";
+    protected EditorDualCamFusion mEditor;
+    protected FilterDualCamFusionRepresentation mRepresentation;
+    private Matrix mToOrig;
+    private float[] mTmpPoint = new float[2];
+    private Bitmap mUnderlay;
+
+    public ImageFusion(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mAllowScaleAndTranslate = true;
+    }
+
+    public ImageFusion(Context context) {
+        super(context);
+        mAllowScaleAndTranslate = true;
+    }
+
+    @Override
+    public boolean onSingleTapConfirmed(MotionEvent event) {
+        Log.d(LOGTAG, "single tap: " + event.getX() + "x" + event.getY());
+        calcScreenMapping();
+        mTmpPoint[0] = event.getX();
+        mTmpPoint[1] = event.getY();
+        mToOrig.mapPoints(mTmpPoint);
+
+        mRepresentation.setPoint((int)mTmpPoint[0], (int)mTmpPoint[1]);
+        mEditor.commitLocalRepresentation();
+        return true;
+    }
+
+    public void setUnderlay(Uri uri) {
+        mRepresentation.setUnderlay(uri);
+
+        mUnderlay = ImageLoader.loadConstrainedBitmap(uri, getContext(), MasterImage.MAX_BITMAP_DIM, new Rect(), false);
+        MasterImage.getImage().setFusionUnderlay(mUnderlay);
+        invalidate();
+    }
+
+    public void setEditor(EditorDualCamFusion editor) {
+        mEditor = editor;
+    }
+
+    public void setRepresentation(FilterDualCamFusionRepresentation representation) {
+        mRepresentation = representation;
+    }
+
+    private void calcScreenMapping() {
+        mToOrig = getScreenToImageMatrix(true);
+    }
+
+    @Override
+    public boolean enableComparison() {
+        return false;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
index b55cc2b..d9b8a53 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java
@@ -22,7 +22,7 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.editors.EditorGrad;
 import com.android.gallery3d.filtershow.filters.FilterGradRepresentation;
 
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java b/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java
index 26c49b1..acc0e4d 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java
@@ -66,6 +66,7 @@
         if (image == null) {
             return;
         }
+        toggleComparisonButtonVisibility();
         GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
         GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, getWidth(),
                 getHeight());
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
index 5186c09..fce31e5 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
@@ -45,7 +45,7 @@
     }
 
     public void rotate() {
-        mLocalRep.rotateCW();
+        mLocalRep.rotateCCW();
         invalidate();
     }
 
@@ -70,6 +70,7 @@
         if (image == null) {
             return;
         }
+        toggleComparisonButtonVisibility();
         GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
         GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, canvas.getWidth(),
                 canvas.getHeight());
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
old mode 100644
new mode 100755
index e2f21f3..02a50b4
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
@@ -16,6 +16,9 @@
 
 package com.android.gallery3d.filtershow.imageshow;
 
+import java.io.File;
+import java.util.ArrayList;
+
 import android.animation.Animator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -24,17 +27,16 @@
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.Region;
 import android.graphics.Shader;
 import android.graphics.drawable.NinePatchDrawable;
 import androidx.core.widget.EdgeEffectCompat;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.GestureDetector;
 import android.view.GestureDetector.OnDoubleTapListener;
 import android.view.GestureDetector.OnGestureListener;
@@ -43,7 +45,7 @@
 import android.view.View;
 import android.widget.LinearLayout;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
@@ -51,12 +53,9 @@
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 import com.android.gallery3d.filtershow.tools.SaveImage;
 
-import java.io.File;
-import java.util.ArrayList;
-
 public class ImageShow extends View implements OnGestureListener,
-        ScaleGestureDetector.OnScaleGestureListener,
-        OnDoubleTapListener {
+                                                ScaleGestureDetector.OnScaleGestureListener,
+                                                OnDoubleTapListener {
 
     private static final String LOGTAG = "ImageShow";
     private static final boolean ENABLE_ZOOMED_COMPARISON = false;
@@ -67,50 +66,44 @@
 
     protected int mBackgroundColor;
 
-    private GestureDetector mGestureDetector = null;
-    private ScaleGestureDetector mScaleGestureDetector = null;
+    protected GestureDetector mGestureDetector = null;
+    protected ScaleGestureDetector mScaleGestureDetector = null;
 
+    private RectF mFusionBounds = new RectF();
     protected Rect mImageBounds = new Rect();
-    private boolean mOriginalDisabled = false;
     private boolean mTouchShowOriginal = false;
-    private long mTouchShowOriginalDate = 0;
-    private final long mTouchShowOriginalDelayMin = 200; // 200ms
-    private int mShowOriginalDirection = 0;
-    private static int UNVEIL_HORIZONTAL = 1;
-    private static int UNVEIL_VERTICAL = 2;
 
     private NinePatchDrawable mShadow = null;
     private Rect mShadowBounds = new Rect();
     private int mShadowMargin = 15; // not scaled, fixed in the asset
     private boolean mShadowDrawn = false;
 
-    private Point mTouchDown = new Point();
-    private Point mTouch = new Point();
-    private boolean mFinishedScalingOperation = false;
+    protected Point mTouchDown = new Point();
+    protected Point mTouch = new Point();
+    protected boolean mFinishedScalingOperation = false;
 
-    private int mOriginalTextMargin;
-    private int mOriginalTextSize;
-    private String mOriginalText;
     private boolean mZoomIn = false;
     Point mOriginalTranslation = new Point();
     float mOriginalScale;
     float mStartFocusX, mStartFocusY;
 
-    private EdgeEffectCompat mEdgeEffect = null;
-    private static final int EDGE_LEFT = 1;
-    private static final int EDGE_TOP = 2;
-    private static final int EDGE_RIGHT = 3;
-    private static final int EDGE_BOTTOM = 4;
-    private int mCurrentEdgeEffect = 0;
-    private int mEdgeSize = 100;
+    protected EdgeEffectCompat mEdgeEffect = null;
+    protected static final int EDGE_LEFT = 1;
+    protected static final int EDGE_TOP = 2;
+    protected static final int EDGE_RIGHT = 3;
+    protected static final int EDGE_BOTTOM = 4;
+    protected int mCurrentEdgeEffect = 0;
+    protected int mEdgeSize = 100;
 
-    private static final int mAnimationSnapDelay = 200;
-    private static final int mAnimationZoomDelay = 400;
-    private ValueAnimator mAnimatorScale = null;
-    private ValueAnimator mAnimatorTranslateX = null;
-    private ValueAnimator mAnimatorTranslateY = null;
+    protected static final int mAnimationSnapDelay = 200;
+    protected static final int mAnimationZoomDelay = 400;
+    protected ValueAnimator mAnimatorScale = null;
+    protected ValueAnimator mAnimatorTranslateX = null;
+    protected ValueAnimator mAnimatorTranslateY = null;
 
-    private enum InteractionMode {
+    protected boolean mAllowScaleAndTranslate = false;
+
+    protected enum InteractionMode {
         NONE,
         SCALE,
         MOVE
@@ -143,6 +136,10 @@
         return MasterImage.getImage().hasModifications();
     }
 
+    public boolean hasFusionApplied() {
+        return MasterImage.getImage().hasFusionApplied();
+    }
+
     public void resetParameter() {
         // TODO: implement reset
     }
@@ -171,10 +168,7 @@
         Resources res = context.getResources();
         mTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_text_size);
         mTextPadding = res.getDimensionPixelSize(R.dimen.photoeditor_text_padding);
-        mOriginalTextMargin = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_margin);
-        mOriginalTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_size);
         mBackgroundColor = res.getColor(R.color.background_screen);
-        mOriginalText = res.getString(R.string.original_picture_text);
         mShadow = (NinePatchDrawable) res.getDrawable(R.drawable.geometry_shadow);
         setupGestureDetector(context);
         mActivity = (FilterShowActivity) context;
@@ -263,34 +257,48 @@
         MasterImage img = MasterImage.getImage();
         // Hide the loading indicator as needed
         if (mActivity.isLoadingVisible() && getFilteredImage() != null) {
-            if ((img.getLoadedPreset() == null)
-                    || (img.getLoadedPreset() != null
-                    && img.getLoadedPreset().equals(img.getCurrentPreset()))) {
-                mActivity.stopLoadingIndicator();
-            } else if (img.getLoadedPreset() != null) {
+            if (img.getLoadedPreset() != null
+                    && !img.getLoadedPreset().equals(img.getCurrentPreset())) {
                 return;
             }
-            mActivity.stopLoadingIndicator();
+        }
+
+        Bitmap fusionUnderlay = MasterImage.getImage().getFusionUnderlay();
+        if(fusionUnderlay != null) {
+            float canvWidth = canvas.getWidth();
+            float canvHeight = canvas.getHeight();
+            float width, height;
+            float underlayAspect = (float)fusionUnderlay.getWidth() / (float)fusionUnderlay.getHeight();
+
+            if(canvHeight * underlayAspect > canvWidth) {
+                // width is constraint
+                width = canvWidth;
+                height = canvWidth / underlayAspect;
+            } else {
+                // height is constraint
+                height = canvHeight;
+                width = canvHeight * underlayAspect;
+            }
+
+            // center in canvas
+            mFusionBounds.top = (canvHeight - height)/2;
+            mFusionBounds.bottom = mFusionBounds.top + height;
+            mFusionBounds.left = (canvWidth - width)/2;
+            mFusionBounds.right = mFusionBounds.left + width;
+
+            canvas.drawBitmap(fusionUnderlay, null, mFusionBounds, null);
+            canvas.clipRect(mFusionBounds);
+            MasterImage.getImage().setFusionBounds(canvas, mFusionBounds);
         }
 
         canvas.save();
 
         mShadowDrawn = false;
 
-        Bitmap highresPreview = MasterImage.getImage().getHighresImage();
-        Bitmap fullHighres = MasterImage.getImage().getPartialImage();
-
-        boolean isDoingNewLookAnimation = MasterImage.getImage().onGoingNewLookAnimation();
-
-        if (highresPreview == null || isDoingNewLookAnimation) {
-            drawImageAndAnimate(canvas, getFilteredImage());
-        } else {
-            drawImageAndAnimate(canvas, highresPreview);
+        if (!drawCompareImage(canvas, MasterImage.getImage().getOriginalBitmapLarge())) {
+            drawImageAndAnimate(canvas, getImageToDraw());
         }
 
-        drawHighresImage(canvas, fullHighres);
-        drawCompareImage(canvas, getGeometryOnlyImage());
-
         canvas.restore();
 
         if (!mEdgeEffect.isFinished()) {
@@ -318,6 +326,17 @@
         }
     }
 
+    protected Bitmap getImageToDraw() {
+        Bitmap highresPreview = MasterImage.getImage().getHighresImage();
+        boolean isDoingNewLookAnimation = MasterImage.getImage().onGoingNewLookAnimation();
+
+        if (highresPreview == null || isDoingNewLookAnimation) {
+            return getFilteredImage();
+        } else {
+            return highresPreview;
+        }
+    }
+
     private void drawHighresImage(Canvas canvas, Bitmap fullHighres) {
         Matrix originalToScreen = MasterImage.getImage().originalImageToScreen();
         if (fullHighres != null && originalToScreen != null) {
@@ -349,8 +368,7 @@
         return MasterImage.getImage().getFilteredImage();
     }
 
-    public void drawImageAndAnimate(Canvas canvas,
-                                    Bitmap image) {
+    public void drawImageAndAnimate(Canvas canvas, Bitmap image) {
         if (image == null) {
             return;
         }
@@ -366,6 +384,8 @@
         m.mapRect(d);
         d.roundOut(mImageBounds);
 
+        master.setImageBounds(canvas, mImageBounds);
+
         boolean showAnimatedImage = master.onGoingNewLookAnimation();
         if (!showAnimatedImage && mDidStartAnimation) {
             // animation ended, but do we have the correct image to show?
@@ -477,12 +497,20 @@
 
             if (needsToDrawImage) {
                 drawShadow(canvas, previousBounds); // as needed
+
+                if(hasFusionApplied() || this instanceof ImageFusion) {
+                    previousImage.setHasAlpha(true);
+                }
                 canvas.drawBitmap(previousImage, mp, mPaint);
             }
 
             canvas.restore();
         } else {
             drawShadow(canvas, mImageBounds); // as needed
+
+            if(hasFusionApplied() || this instanceof ImageFusion) {
+                image.setHasAlpha(true);
+            }
             canvas.drawBitmap(image, m, mPaint);
         }
 
@@ -504,7 +532,7 @@
     }
 
     private void drawShadow(Canvas canvas, Rect d) {
-        if (!mShadowDrawn) {
+        if (!mShadowDrawn && !hasFusionApplied() && !(this instanceof ImageFusion)) {
             mShadowBounds.set(d.left - mShadowMargin, d.top - mShadowMargin,
                     d.right + mShadowMargin, d.bottom + mShadowMargin);
             mShadow.setBounds(mShadowBounds);
@@ -513,78 +541,18 @@
         }
     }
 
-    public void drawCompareImage(Canvas canvas, Bitmap image) {
+    public boolean drawCompareImage(Canvas canvas, Bitmap image) {
         MasterImage master = MasterImage.getImage();
         boolean showsOriginal = master.showsOriginal();
         if (!showsOriginal && !mTouchShowOriginal)
-            return;
+            return false;
         canvas.save();
         if (image != null) {
-            if (mShowOriginalDirection == 0) {
-                if (Math.abs(mTouch.y - mTouchDown.y) > Math.abs(mTouch.x - mTouchDown.x)) {
-                    mShowOriginalDirection = UNVEIL_VERTICAL;
-                } else {
-                    mShowOriginalDirection = UNVEIL_HORIZONTAL;
-                }
-            }
-
-            int px = 0;
-            int py = 0;
-            if (mShowOriginalDirection == UNVEIL_VERTICAL) {
-                px = mImageBounds.width();
-                py = mTouch.y - mImageBounds.top;
-            } else {
-                px = mTouch.x - mImageBounds.left;
-                py = mImageBounds.height();
-                if (showsOriginal) {
-                    px = mImageBounds.width();
-                }
-            }
-
-            Rect d = new Rect(mImageBounds.left, mImageBounds.top,
-                    mImageBounds.left + px, mImageBounds.top + py);
-            if (mShowOriginalDirection == UNVEIL_HORIZONTAL) {
-                if (mTouchDown.x - mTouch.x > 0) {
-                    d.set(mImageBounds.left + px, mImageBounds.top,
-                            mImageBounds.right, mImageBounds.top + py);
-                }
-            } else {
-                if (mTouchDown.y - mTouch.y > 0) {
-                    d.set(mImageBounds.left, mImageBounds.top + py,
-                            mImageBounds.left + px, mImageBounds.bottom);
-                }
-            }
-            canvas.clipRect(d);
             Matrix m = master.computeImageToScreen(image, 0, false);
             canvas.drawBitmap(image, m, mPaint);
-            Paint paint = new Paint();
-            paint.setColor(Color.BLACK);
-            paint.setStrokeWidth(3);
-
-            if (mShowOriginalDirection == UNVEIL_VERTICAL) {
-                canvas.drawLine(mImageBounds.left, mTouch.y,
-                        mImageBounds.right, mTouch.y, paint);
-            } else {
-                canvas.drawLine(mTouch.x, mImageBounds.top,
-                        mTouch.x, mImageBounds.bottom, paint);
-            }
-
-            Rect bounds = new Rect();
-            paint.setAntiAlias(true);
-            paint.setTextSize(mOriginalTextSize);
-            paint.getTextBounds(mOriginalText, 0, mOriginalText.length(), bounds);
-            paint.setColor(Color.BLACK);
-            paint.setStyle(Paint.Style.STROKE);
-            paint.setStrokeWidth(3);
-            canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
-                    mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
-            paint.setStyle(Paint.Style.FILL);
-            paint.setStrokeWidth(1);
-            paint.setColor(Color.WHITE);
-            canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin,
-                    mImageBounds.top + bounds.height() + mOriginalTextMargin, paint);
         }
         canvas.restore();
+        return true;
     }
 
     public void bindAsImageLoadListener() {
@@ -614,9 +582,12 @@
         int action = event.getAction();
         action = action & MotionEvent.ACTION_MASK;
 
-        mGestureDetector.onTouchEvent(event);
+        if(!hasFusionApplied() || mAllowScaleAndTranslate)
+            mGestureDetector.onTouchEvent(event);
         boolean scaleInProgress = scaleInProgress();
-        mScaleGestureDetector.onTouchEvent(event);
+        if(!hasFusionApplied() || mAllowScaleAndTranslate)
+            mScaleGestureDetector.onTouchEvent(event);
+
         if (mInteractionMode == InteractionMode.SCALE) {
             return true;
         }
@@ -632,8 +603,6 @@
             mInteractionMode = InteractionMode.MOVE;
             mTouchDown.x = ex;
             mTouchDown.y = ey;
-            mTouchShowOriginalDate = System.currentTimeMillis();
-            mShowOriginalDirection = 0;
             MasterImage.getImage().setOriginalTranslation(MasterImage.getImage().getTranslation());
         }
 
@@ -642,7 +611,8 @@
             mTouch.y = ey;
 
             float scaleFactor = MasterImage.getImage().getScaleFactor();
-            if (scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2)) {
+            if ((scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2) && !hasFusionApplied())
+                    || mAllowScaleAndTranslate) {
                 float translateX = (mTouch.x - mTouchDown.x) / scaleFactor;
                 float translateY = (mTouch.y - mTouchDown.y) / scaleFactor;
                 Point originalTranslation = MasterImage.getImage().getOriginalTranslation();
@@ -650,12 +620,6 @@
                 translation.x = (int) (originalTranslation.x + translateX);
                 translation.y = (int) (originalTranslation.y + translateY);
                 MasterImage.getImage().setTranslation(translation);
-                mTouchShowOriginal = false;
-            } else if (enableComparison() && !mOriginalDisabled
-                    && (System.currentTimeMillis() - mTouchShowOriginalDate
-                            > mTouchShowOriginalDelayMin)
-                    && event.getPointerCount() == 1) {
-                mTouchShowOriginal = true;
             }
         }
 
@@ -663,12 +627,12 @@
                 || action == MotionEvent.ACTION_CANCEL
                 || action == MotionEvent.ACTION_OUTSIDE) {
             mInteractionMode = InteractionMode.NONE;
-            mTouchShowOriginal = false;
             mTouchDown.x = 0;
             mTouchDown.y = 0;
             mTouch.x = 0;
             mTouch.y = 0;
-            if (MasterImage.getImage().getScaleFactor() <= 1) {
+            if (!(mAllowScaleAndTranslate || hasFusionApplied()) &&
+                    MasterImage.getImage().getScaleFactor() <= 1) {
                 MasterImage.getImage().setScaleFactor(1);
                 MasterImage.getImage().resetTranslation();
             }
@@ -684,7 +648,7 @@
     }
 
     private void startAnimTranslation(int fromX, int toX,
-                                      int fromY, int toY, int delay) {
+            int fromY, int toY, int delay) {
         if (fromX == toX && fromY == toY) {
             return;
         }
@@ -729,8 +693,8 @@
 
         if (x != translation.x || y != translation.y) {
             startAnimTranslation(x, translation.x,
-                                 y, translation.y,
-                                 mAnimationSnapDelay);
+                    y, translation.y,
+                    mAnimationSnapDelay);
         }
     }
 
@@ -740,6 +704,9 @@
 
     @Override
     public boolean onDoubleTap(MotionEvent arg0) {
+        if(hasFusionApplied())
+            return true;
+
         mZoomIn = !mZoomIn;
         float scale = 1.0f;
         final float x = arg0.getX();
@@ -754,7 +721,7 @@
             mAnimatorScale = ValueAnimator.ofFloat(
                     MasterImage.getImage().getScaleFactor(),
                     scale
-            );
+                    );
             float translateX = (getWidth() / 2 - x);
             float translateY = (getHeight() / 2 - y);
             Point translation = MasterImage.getImage().getTranslation();
@@ -770,8 +737,8 @@
             constrainTranslation(translation, scale);
 
             startAnimTranslation(startTranslateX, translation.x,
-                                 startTranslateY, translation.y,
-                                 mAnimationZoomDelay);
+                    startTranslateY, translation.y,
+                    mAnimationZoomDelay);
             mAnimatorScale.setDuration(mAnimationZoomDelay);
             mAnimatorScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                 @Override
@@ -807,15 +774,18 @@
         return true;
     }
 
-    private void constrainTranslation(Point translation, float scale) {
+    protected void constrainTranslation(Point translation, float scale) {
         int currentEdgeEffect = 0;
-        if (scale <= 1) {
+        if (mAllowScaleAndTranslate || scale <= 1) {
             mCurrentEdgeEffect = 0;
             mEdgeEffect.finish();
             return;
         }
 
         Matrix originalToScreen = MasterImage.getImage().originalImageToScreen();
+        if (originalToScreen == null) {
+            return;//if the bitmap loading task is not complete, don't response to touch event
+        }
         Rect originalBounds = MasterImage.getImage().getOriginalBounds();
         RectF screenPos = new RectF(originalBounds);
         originalToScreen.mapRect(screenPos);
@@ -929,9 +899,11 @@
         if (scaleFactor > MasterImage.getImage().getMaxScaleFactor()) {
             scaleFactor = MasterImage.getImage().getMaxScaleFactor();
         }
-        if (scaleFactor < 1.0f) {
+
+        if (!mAllowScaleAndTranslate && scaleFactor < 1.0f) {
             scaleFactor = 1.0f;
         }
+
         MasterImage.getImage().setScaleFactor(scaleFactor);
         scaleFactor = img.getScaleFactor();
         float focusx = detector.getFocusX();
@@ -961,7 +933,8 @@
     @Override
     public void onScaleEnd(ScaleGestureDetector detector) {
         mInteractionMode = InteractionMode.NONE;
-        if (MasterImage.getImage().getScaleFactor() < 1) {
+        if (!mAllowScaleAndTranslate &&
+                MasterImage.getImage().getScaleFactor() < 1) {
             MasterImage.getImage().setScaleFactor(1);
             invalidate();
         }
@@ -975,4 +948,31 @@
         return false;
     }
 
+    public void scaleImage(boolean isScaled, Context context) {
+        float scale = 1.0f;
+        Bitmap bitmap = MasterImage.getImage().getOriginalBitmapLarge();
+        if(bitmap == null)
+            return;
+        int bitmapWidth = bitmap.getWidth();
+        int bitmapheight = bitmap.getHeight();
+
+//        int width = MasterImage.getImage().getOriginalBounds().width();
+//        int height = MasterImage.getImage().getOriginalBounds().height();
+        int width = getWidth();
+        int height = getHeight();
+        int scaledWidth = context.getResources().getDimensionPixelSize(R.dimen.scaled_image_width);
+        int scaledHeight = context.getResources().getDimensionPixelSize(R.dimen.scaled_image_height);
+        if (isScaled) {
+          scale = (float) scaledHeight / height  ;
+        }
+        MasterImage.getImage().setScaleFactor(scale);
+
+        invalidate();
+    }
+
+    public void toggleComparisonButtonVisibility()
+    {
+       mActivity.toggleComparisonButtonVisibility();
+    }
+
 }
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
index 4742f2e..d83c0ad 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
@@ -29,6 +29,7 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.crop.CropDrawingUtils;
 import com.android.gallery3d.filtershow.editors.EditorStraighten;
 import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
@@ -223,6 +224,9 @@
             ih = imageHeight;
         }
         float scale = GeometryMathUtils.scale(iw, ih, viewWidth, viewHeight);
+        if (scale > 3.0f) {
+            scale = 3.0f;
+        }
         scale *= GeometryMathUtils.SHOW_SCALE;
         GeometryMathUtils.scaleRect(tmp, scale);
         getUntranslatedStraightenCropBounds(tmp, mAngle);
@@ -246,6 +250,7 @@
             MasterImage.getImage().invalidateFiltersOnly();
             return;
         }
+        toggleComparisonButtonVisibility();
         GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep);
         mDrawHolder.straighten = mAngle;
         int imageWidth = image.getWidth();
@@ -253,9 +258,11 @@
         int viewWidth = canvas.getWidth();
         int viewHeight = canvas.getHeight();
 
+        int panelHeight = getContext().getResources().getDimensionPixelOffset(
+                R.dimen.category_actionbar_panel_height);
         // Get matrix for drawing bitmap
         Matrix m = GeometryMathUtils.getFullGeometryToScreenMatrix(mDrawHolder, imageWidth,
-                imageHeight, viewWidth, viewHeight);
+                imageHeight, viewWidth, viewHeight - panelHeight);
         mPaint.reset();
         mPaint.setAntiAlias(true);
         mPaint.setFilterBitmap(true);
@@ -266,7 +273,7 @@
         mPaint.setStrokeWidth(2);
         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
         updateCurrentCrop(m, mDrawHolder, mDrawRect, imageWidth,
-                imageHeight, viewWidth, viewHeight);
+                imageHeight, viewWidth, viewHeight - panelHeight);
         if (mFirstDrawSinceUp) {
             mPriorCropAtUp.set(mCrop);
             mLocalRep.setStraighten(mAngle);
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java
new file mode 100644
index 0000000..dcce40e
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitFusion.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.util.AttributeSet;
+
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitFusion;
+import com.android.gallery3d.filtershow.filters.FilterTruePortraitFusionRepresentation;
+
+public class ImageTruePortraitFusion extends ImageShow {
+    private static final String LOGTAG = "ImageTruePortraitFusion";
+    protected EditorTruePortraitFusion mEditor;
+    protected FilterTruePortraitFusionRepresentation mRepresentation;
+    private Bitmap mUnderlay;
+
+    public ImageTruePortraitFusion(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mAllowScaleAndTranslate = true;
+    }
+
+    public ImageTruePortraitFusion(Context context) {
+        super(context);
+        mAllowScaleAndTranslate = true;
+    }
+
+    public void setUnderlay(Uri uri) {
+        mRepresentation.setUnderlay(uri);
+
+        if(mUnderlay != null) {
+            mUnderlay.recycle();
+            mUnderlay = null;
+            MasterImage.getImage().setFusionUnderlay(null);
+        }
+
+        mUnderlay = ImageLoader.loadConstrainedBitmap(uri, getContext(), MasterImage.MAX_BITMAP_DIM, new Rect(), false);
+        int ori = ImageLoader.getMetadataOrientation(getContext(), uri);
+        if (ori != ImageLoader.ORI_NORMAL) {
+            mUnderlay = ImageLoader.orientBitmap(mUnderlay, ori);
+        }
+        MasterImage.getImage().setFusionUnderlay(mUnderlay);
+        invalidate();
+    }
+
+    public void setEditor(EditorTruePortraitFusion editor) {
+        mEditor = editor;
+    }
+
+    public void setRepresentation(FilterTruePortraitFusionRepresentation representation) {
+        mRepresentation = representation;
+    }
+
+    @Override
+    public boolean enableComparison() {
+        return false;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitMask.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitMask.java
new file mode 100644
index 0000000..43193ac
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageTruePortraitMask.java
@@ -0,0 +1,679 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * 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.gallery3d.filtershow.imageshow;
+
+import java.util.Arrays;
+import java.util.Stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.LightingColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+
+import com.android.gallery3d.filtershow.editors.EditorTruePortraitMask;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
+import com.android.gallery3d.filtershow.tools.TruePortraitNativeEngine;
+
+public class ImageTruePortraitMask extends ImageShow {
+
+    private static final String LOGTAG = "ImageTruePortraitMask";
+
+    private boolean mZoomIn = false;
+    private Point mScaleTranslation = new Point();
+    private float mScaleStartFocusX, mScaleStartFocusY;
+
+    private Point mTranslation = new Point();
+    private Point mOriginalTranslation = new Point();
+    private float mScaleFactor = 1f;
+    private float mMaxScaleFactor = 3f;
+
+    private Paint mMaskPaintForeground = new Paint();
+    private Paint mMaskPaintBackground = new Paint();
+    private Paint mMaskEditPaint = new Paint();
+
+    private StrokeData mCurrent;
+    private Stack<StrokeData> mDrawing = new Stack<StrokeData>();
+
+    private EditorTruePortraitMask mEditor;
+    private Bitmap mPreview;
+    private Bitmap mOriginalMask;
+    private Bitmap mMask;
+
+    private Mode mMode = Mode.MODE_NONE;
+    private enum Mode {
+        MODE_NONE,
+        MODE_MOVE,
+        MODE_SCALE,
+        MODE_DRAW
+    }
+
+    public ImageTruePortraitMask(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        setup();
+    }
+
+    public ImageTruePortraitMask(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setup();
+    }
+
+    public ImageTruePortraitMask(Context context) {
+        super(context);
+        setup();
+    }
+
+    private void setup() {
+        mMaskPaintForeground.setAntiAlias(true);
+        mMaskPaintForeground.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
+        mMaskPaintForeground.setColorFilter(new ColorMatrixColorFilter(new float[] {
+                // Set color to GREEN
+                0,0,0,0,0,
+                0,0,0,0,191,
+                0,0,0,0,0,
+                0,0,0,.5f,0
+        }));
+
+        mMaskPaintBackground.setAntiAlias(true);
+        mMaskPaintBackground.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
+        mMaskPaintBackground.setColorFilter(new ColorMatrixColorFilter(new float[] {
+                // Set color to RED and inverse ALPHA channel
+                // of original mask to get background
+                0,0,0,0,191,
+                0,0,0,0,0,
+                0,0,0,0,0,
+                0,0,0,-.5f,127
+        }));
+
+        mMaskEditPaint.setAntiAlias(true);
+        mMaskEditPaint.setStyle(Style.STROKE);
+        mMaskEditPaint.setStrokeCap(Paint.Cap.ROUND);
+    }
+
+    @Override
+    public void attach() {
+        mPreview = TruePortraitNativeEngine.getInstance().getPreview();
+        mOriginalMask = TruePortraitNativeEngine.getInstance().getMask();
+        mMask = Bitmap.createBitmap(mOriginalMask.getWidth(), mOriginalMask.getHeight(), mOriginalMask.getConfig());
+    }
+
+    @Override
+    public void detach() {
+        if(mPreview != null) {
+            mPreview.recycle();
+            mPreview = null;
+        }
+
+        if(mOriginalMask != null) {
+            mOriginalMask.recycle();
+            mOriginalMask = null;
+        }
+
+        if(mMask != null) {
+            mMask.recycle();
+            mMask = null;
+        }
+
+        mDrawing.clear();
+    }
+
+    public void setEditor(EditorTruePortraitMask editor) {
+        mEditor = editor;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        toggleComparisonButtonVisibility();
+
+        mPaint.reset();
+        mPaint.setAntiAlias(true);
+        mPaint.setFilterBitmap(true);
+
+        drawImage(canvas, mPreview, mPaint);
+        updateEditsToMask(mMask);
+        drawImage(canvas, mMask,
+                mEditor.isBackgroundMode()?mMaskPaintBackground:mMaskPaintForeground);
+
+        if (!mEdgeEffect.isFinished()) {
+            canvas.save();
+            float dx = (getHeight() - getWidth()) / 2f;
+            if (getWidth() > getHeight()) {
+                dx = - (getWidth() - getHeight()) / 2f;
+            }
+            if (mCurrentEdgeEffect == EDGE_BOTTOM) {
+                canvas.rotate(180, getWidth()/2, getHeight()/2);
+            } else if (mCurrentEdgeEffect == EDGE_RIGHT) {
+                canvas.rotate(90, getWidth()/2, getHeight()/2);
+                canvas.translate(0, dx);
+            } else if (mCurrentEdgeEffect == EDGE_LEFT) {
+                canvas.rotate(270, getWidth()/2, getHeight()/2);
+                canvas.translate(0, dx);
+            }
+            if (mCurrentEdgeEffect != 0) {
+                mEdgeEffect.draw(canvas);
+            }
+            canvas.restore();
+            invalidate();
+        } else {
+            mCurrentEdgeEffect = 0;
+        }
+    }
+
+    private void drawImage(Canvas canvas, Bitmap image, Paint paint) {
+        if (image == null) {
+            return;
+        }
+
+        Matrix m = computeImageToScreen(image.getWidth(), image.getHeight());
+        if (m == null) {
+            return;
+        }
+
+        canvas.save();
+        image.setHasAlpha(true);
+        canvas.drawBitmap(image, m, paint);
+        canvas.restore();
+    }
+
+    private void updateEditsToMask(Bitmap mask) {
+        // clear mask and reset with original
+        mask.eraseColor(Color.TRANSPARENT);
+        Canvas canvas = new Canvas(mask);
+        canvas.drawBitmap(mOriginalMask, 0, 0, null);
+
+        for(StrokeData sd:mDrawing) {
+            drawEdit(canvas, sd);
+        }
+
+        // update current edit
+        if(mCurrent != null) {
+            drawEdit(canvas, mCurrent);
+        }
+    }
+
+    private void drawEdit(Canvas canvas, StrokeData sd) {
+        if (sd == null) {
+            return;
+        }
+        if (sd.mPath == null) {
+            return;
+        }
+        mMaskEditPaint.setColor(sd.mColor);
+        if(sd.mColor == Color.TRANSPARENT)
+            mMaskEditPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+        else
+            mMaskEditPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+        mMaskEditPaint.setStrokeWidth(sd.mRadius);
+
+        canvas.drawPath(sd.mPath, mMaskEditPaint);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        int action = event.getAction();
+        action = action & MotionEvent.ACTION_MASK;
+
+        boolean scaleInProgress = scaleInProgress();
+        mGestureDetector.onTouchEvent(event);
+        mScaleGestureDetector.onTouchEvent(event);
+
+        if (mMode == Mode.MODE_SCALE) {
+            return true;
+        }
+        if (!scaleInProgress() && scaleInProgress) {
+            // If we were scaling, the scale will stop but we will
+            // still issue an ACTION_UP. Let the subclasses know.
+            mFinishedScalingOperation = true;
+        }
+
+        int ex = (int) event.getX();
+        int ey = (int) event.getY();
+        if (action == MotionEvent.ACTION_DOWN) {
+            mTouchDown.x = ex;
+            mTouchDown.y = ey;
+            if(event.getPointerCount() == 2) {
+                mMode = Mode.MODE_MOVE;
+                setOriginalTranslation(getTranslation());
+            } else if (event.getPointerCount() == 1) {
+                mMode = Mode.MODE_DRAW;
+                Point mapPoint = mapPoint(ex, ey);
+                startNewSection(mapPoint.x, mapPoint.y);
+            }
+        } else if (action == MotionEvent.ACTION_MOVE) {
+            mTouch.x = ex;
+            mTouch.y = ey;
+
+            float scaleFactor = getScaleFactor();
+            if (scaleFactor > 1 && event.getPointerCount() == 2
+                    && mMode == Mode.MODE_MOVE) {
+                float translateX = (mTouch.x - mTouchDown.x) / scaleFactor;
+                float translateY = (mTouch.y - mTouchDown.y) / scaleFactor;
+                Point originalTranslation = getOriginalTranslation();
+                Point translation = getTranslation();
+                translation.x = (int) (originalTranslation.x + translateX);
+                translation.y = (int) (originalTranslation.y + translateY);
+                setTranslation(translation);
+            } else if(event.getPointerCount() == 1
+                    && mMode == Mode.MODE_DRAW) {
+                Point mapPoint = mapPoint(ex, ey);
+                addPoint(mapPoint.x, mapPoint.y);
+            }
+        } else if (action == MotionEvent.ACTION_UP
+                || action == MotionEvent.ACTION_CANCEL
+                || action == MotionEvent.ACTION_OUTSIDE) {
+            if(event.getPointerCount() == 1
+                    && mMode == Mode.MODE_DRAW) {
+                Point mapPoint = mapPoint(ex, ey);
+                endSection(mapPoint.x, mapPoint.y);
+            }
+
+            mMode = Mode.MODE_NONE;
+            mTouchDown.x = 0;
+            mTouchDown.y = 0;
+            mTouch.x = 0;
+            mTouch.y = 0;
+            if (getScaleFactor() <= 1) {
+                setScaleFactor(1);
+                setTranslation(new Point(0,0));
+            }
+        }
+
+        float scaleFactor = getScaleFactor();
+        Point translation = getTranslation();
+        constrainTranslation(translation, scaleFactor);
+        setTranslation(translation);
+
+        invalidate();
+        return true;
+    }
+
+    private void startAnimTranslation(int fromX, int toX,
+            int fromY, int toY, int delay) {
+        if (fromX == toX && fromY == toY) {
+            return;
+        }
+        if (mAnimatorTranslateX != null) {
+            mAnimatorTranslateX.cancel();
+        }
+        if (mAnimatorTranslateY != null) {
+            mAnimatorTranslateY.cancel();
+        }
+        mAnimatorTranslateX = ValueAnimator.ofInt(fromX, toX);
+        mAnimatorTranslateY = ValueAnimator.ofInt(fromY, toY);
+        mAnimatorTranslateX.setDuration(delay);
+        mAnimatorTranslateY.setDuration(delay);
+        mAnimatorTranslateX.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                Point translation = getTranslation();
+                translation.x = (Integer) animation.getAnimatedValue();
+                setTranslation(translation);
+                invalidate();
+            }
+        });
+        mAnimatorTranslateY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                Point translation = getTranslation();
+                translation.y = (Integer) animation.getAnimatedValue();
+                setTranslation(translation);
+                invalidate();
+            }
+        });
+        mAnimatorTranslateX.start();
+        mAnimatorTranslateY.start();
+    }
+
+    private void applyTranslationConstraints() {
+        float scaleFactor = getScaleFactor();
+        Point translation = getTranslation();
+        int x = translation.x;
+        int y = translation.y;
+        constrainTranslation(translation, scaleFactor);
+
+        if (x != translation.x || y != translation.y) {
+            startAnimTranslation(x, translation.x,
+                    y, translation.y,
+                    mAnimationSnapDelay);
+        }
+    }
+
+    @Override
+    public boolean onDoubleTap(MotionEvent arg0) {
+        if(hasFusionApplied())
+            return true;
+
+        mZoomIn = !mZoomIn;
+        float scale = 1.0f;
+        final float x = arg0.getX();
+        final float y = arg0.getY();
+        if (mZoomIn) {
+            scale = getMaxScaleFactor();
+        }
+        if (scale != getScaleFactor()) {
+            if (mAnimatorScale != null) {
+                mAnimatorScale.cancel();
+            }
+            mAnimatorScale = ValueAnimator.ofFloat(
+                    getScaleFactor(),
+                    scale
+                    );
+            float translateX = (getWidth() / 2 - x);
+            float translateY = (getHeight() / 2 - y);
+            Point translation = getTranslation();
+            int startTranslateX = translation.x;
+            int startTranslateY = translation.y;
+            if (scale != 1.0f) {
+                translation.x = (int) (mScaleTranslation.x + translateX);
+                translation.y = (int) (mScaleTranslation.y + translateY);
+            } else {
+                translation.x = 0;
+                translation.y = 0;
+            }
+            constrainTranslation(translation, scale);
+
+            startAnimTranslation(startTranslateX, translation.x,
+                    startTranslateY, translation.y,
+                    mAnimationZoomDelay);
+            mAnimatorScale.setDuration(mAnimationZoomDelay);
+            mAnimatorScale.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                @Override
+                public void onAnimationUpdate(ValueAnimator animation) {
+                    setScaleFactor((Float) animation.getAnimatedValue());
+                    invalidate();
+                }
+            });
+            mAnimatorScale.addListener(new Animator.AnimatorListener() {
+                @Override
+                public void onAnimationStart(Animator animation) {
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    applyTranslationConstraints();
+                    invalidate();
+                }
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+
+                }
+
+                @Override
+                public void onAnimationRepeat(Animator animation) {
+
+                }
+            });
+            mAnimatorScale.start();
+        }
+        return true;
+    }
+
+    protected void constrainTranslation(Point translation, float scale) {
+        int currentEdgeEffect = 0;
+        if (mAllowScaleAndTranslate || scale <= 1) {
+            mCurrentEdgeEffect = 0;
+            mEdgeEffect.finish();
+            return;
+        }
+
+        Rect originalBounds = MasterImage.getImage().getOriginalBounds();
+        Matrix originalToScreen = computeImageToScreen(originalBounds.width(), originalBounds.height());
+        RectF screenPos = new RectF(originalBounds);
+        originalToScreen.mapRect(screenPos);
+
+        boolean rightConstraint = screenPos.right < getWidth();
+        boolean leftConstraint = screenPos.left > 0;
+        boolean topConstraint = screenPos.top > 0;
+        boolean bottomConstraint = screenPos.bottom < getHeight();
+
+        if (screenPos.width() > getWidth()) {
+            if (rightConstraint && !leftConstraint) {
+                float tx = screenPos.right - translation.x * scale;
+                translation.x = (int) ((getWidth() - tx) / scale);
+                currentEdgeEffect = EDGE_RIGHT;
+            } else if (leftConstraint && !rightConstraint) {
+                float tx = screenPos.left - translation.x * scale;
+                translation.x = (int) ((-tx) / scale);
+                currentEdgeEffect = EDGE_LEFT;
+            }
+        } else {
+            float tx = screenPos.right - translation.x * scale;
+            float dx = (getWidth() - screenPos.width()) / 2f;
+            translation.x = (int) ((getWidth() - tx - dx) / scale);
+        }
+
+        if (screenPos.height() > getHeight()) {
+            if (bottomConstraint && !topConstraint) {
+                float ty = screenPos.bottom - translation.y * scale;
+                translation.y = (int) ((getHeight() - ty) / scale);
+                currentEdgeEffect = EDGE_BOTTOM;
+            } else if (topConstraint && !bottomConstraint) {
+                float ty = screenPos.top - translation.y * scale;
+                translation.y = (int) ((-ty) / scale);
+                currentEdgeEffect = EDGE_TOP;
+            }
+        } else {
+            float ty = screenPos.bottom - translation.y * scale;
+            float dy = (getHeight()- screenPos.height()) / 2f;
+            translation.y = (int) ((getHeight() - ty - dy) / scale);
+        }
+
+        if (mCurrentEdgeEffect != currentEdgeEffect) {
+            if (mCurrentEdgeEffect == 0 || currentEdgeEffect != 0) {
+                mCurrentEdgeEffect = currentEdgeEffect;
+                mEdgeEffect.finish();
+            }
+            mEdgeEffect.setSize(getWidth(), mEdgeSize);
+        }
+        if (currentEdgeEffect != 0) {
+            mEdgeEffect.onPull(mEdgeSize);
+        }
+    }
+
+    @Override
+    public boolean onScale(ScaleGestureDetector detector) {
+        float scaleFactor = getScaleFactor();
+
+        scaleFactor = scaleFactor * detector.getScaleFactor();
+        if (scaleFactor > getMaxScaleFactor()) {
+            scaleFactor = getMaxScaleFactor();
+        }
+
+        if (scaleFactor < 1.0f) {
+            scaleFactor = 1.0f;
+        }
+
+        setScaleFactor(scaleFactor);
+        float focusx = detector.getFocusX();
+        float focusy = detector.getFocusY();
+        float translateX = (focusx - mScaleStartFocusX) / scaleFactor;
+        float translateY = (focusy - mScaleStartFocusY) / scaleFactor;
+        Point translation = getTranslation();
+        translation.x = (int) (mScaleTranslation.x + translateX);
+        translation.y = (int) (mScaleTranslation.y + translateY);
+        setTranslation(translation);
+        invalidate();
+        return true;
+    }
+
+    @Override
+    public boolean onScaleBegin(ScaleGestureDetector detector) {
+        Point pos = getTranslation();
+        mScaleTranslation.x = pos.x;
+        mScaleTranslation.y = pos.y;
+        mScaleStartFocusX = detector.getFocusX();
+        mScaleStartFocusY = detector.getFocusY();
+        mMode = Mode.MODE_SCALE;
+        return true;
+    }
+
+    @Override
+    public void onScaleEnd(ScaleGestureDetector detector) {
+        mMode = Mode.MODE_NONE;
+        if (getScaleFactor() < 1) {
+            setScaleFactor(1);
+            invalidate();
+        }
+    }
+
+    @Override
+    public boolean hasFusionApplied() {
+        return false;
+    }
+
+    private Matrix computeImageToScreen(int bmWidth, int bmHeight) {
+        float scale = 1f;
+        float translateX = 0;
+        float translateY = 0;
+
+        RectF size = new RectF(0, 0,
+                bmWidth, bmHeight);
+        float scaleW = getWidth() / size.width();
+        float scaleH = getHeight() / size.height();
+        scale = Math.min(scaleW, scaleH);
+        translateX = (getWidth() - (size.width() * scale)) / 2.0f;
+        translateY = (getHeight() - (size.height() * scale)) / 2.0f;
+
+        Point translation = getTranslation();
+        Matrix m = new Matrix();
+        m.postScale(scale, scale);
+        m.postTranslate(translateX, translateY);
+        m.postScale(getScaleFactor(), getScaleFactor(),
+                getWidth() / 2.0f,
+                getHeight() / 2.0f);
+        m.postTranslate(translation.x * getScaleFactor(),
+                translation.y * getScaleFactor());
+        return m;
+    }
+
+    private Matrix computeScreenToImage(int bmWidth, int bmHeight) {
+        Matrix m = computeImageToScreen(bmWidth, bmHeight);
+        Matrix inverse = new Matrix();
+        m.invert(inverse);
+        return inverse;
+    }
+
+    private Point mapPoint(int x, int y) {
+        Matrix screenToImage = computeScreenToImage(mMask.getWidth(), mMask.getHeight());
+        float[] tmpPoint = {x,y};
+        screenToImage.mapPoints(tmpPoint);
+
+        return new Point((int)tmpPoint[0], (int)tmpPoint[1]);
+    }
+
+    private void setTranslation(Point translation) {
+        mTranslation.x = translation.x;
+        mTranslation.y = translation.y;
+    }
+
+    private void setOriginalTranslation(Point translation) {
+        mOriginalTranslation.x = translation.x;
+        mOriginalTranslation.y = translation.y;
+    }
+
+    private void setScaleFactor(float scale) {
+        mScaleFactor = scale;
+    }
+
+    private Point getTranslation() {
+        return mTranslation;
+    }
+
+    private Point getOriginalTranslation() {
+        return mOriginalTranslation;
+    }
+
+    private float getScaleFactor() {
+        return mScaleFactor;
+    }
+
+    private float getMaxScaleFactor() {
+        return mMaxScaleFactor;
+    }
+
+    private void fillStrokeParameters(StrokeData sd){
+        sd.mColor = mEditor.isBackgroundMode()?Color.TRANSPARENT:Color.BLACK;
+        sd.mRadius = mEditor.getBrushSize();
+    }
+
+    private void startNewSection(float x, float y) {
+        mCurrent = new StrokeData();
+        fillStrokeParameters(mCurrent);
+        mCurrent.mPath = new Path();
+        mCurrent.mPath.moveTo(x, y);
+        mCurrent.mPoints[0] = x;
+        mCurrent.mPoints[1] = y;
+        mCurrent.noPoints = 1;
+    }
+
+    private void addPoint(float x, float y) {
+        int len = mCurrent.noPoints * 2;
+        mCurrent.mPath.lineTo(x, y);
+        if ((len+2) > mCurrent.mPoints.length) {
+            mCurrent.mPoints = Arrays.copyOf(mCurrent.mPoints, mCurrent.mPoints.length * 2);
+        }
+        mCurrent.mPoints[len] = x;
+        mCurrent.mPoints[len + 1] = y;
+        mCurrent.noPoints++;
+    }
+
+    private void endSection(float x, float y) {
+        addPoint(x, y);
+        mDrawing.push(mCurrent);
+        mCurrent = null;
+        mEditor.refreshUndoButton();
+    }
+
+    private void resetDrawing() {
+        mCurrent = null;
+    }
+
+    public boolean canUndoEdit() {
+        return !mDrawing.isEmpty();
+    }
+
+    public void undoLastEdit() {
+        if(!mDrawing.isEmpty()) {
+            mDrawing.pop();
+            mEditor.refreshUndoButton();
+            invalidate();
+        }
+    }
+
+    public void applyMaskUpdates() {
+        TruePortraitNativeEngine.getInstance().updateMask(mDrawing);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTrueScanner.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTrueScanner.java
new file mode 100755
index 0000000..d72ec37
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageTrueScanner.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.imageshow;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import com.android.gallery3d.filtershow.crop.CropDrawingUtils;
+import com.android.gallery3d.filtershow.crop.CropMath;
+import com.android.gallery3d.filtershow.crop.CropObject;
+import com.android.gallery3d.filtershow.editors.TrueScannerEditor;
+import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
+import com.android.gallery3d.filtershow.filters.TrueScannerActs;
+
+import org.codeaurora.gallery.R;
+
+public class ImageTrueScanner extends ImageShow {
+    private static final String TAG = ImageTrueScanner.class.getSimpleName();
+    TrueScannerEditor mEditor;
+    private Matrix mDisplayMatrix;
+    private GeometryMathUtils.GeometryHolder mGeometry;
+    public final static int POINT_NUMS = 4;
+    private static float[] mSegPoints = new float[POINT_NUMS*2+4];
+    private boolean[] isTouched = new boolean[POINT_NUMS];
+    private RectF mBitmapBound = new RectF();
+    private Bitmap mBitmap;
+    private Paint mSegmentPaint;
+    private Paint mGlareRemovalTextPaint;
+    private int mGlareButtonX = -1000;
+    private int mGlareButtonY = -1000;
+    private final static float RADIUS = 20f;
+    private final static float CHECK_RADIUS = 100f;
+    private int mMarginalGapX = 10;
+    private int mMarginalGapY = 10;
+    private boolean isDetectedPointsApplied = false;
+    private static boolean mIsCordsUIShowing = true;
+    private int[] mDetectedPoints = null;
+    private static boolean mIsGlareButtonPressed = false;
+    private Paint mGrayPaint;
+    private Bitmap mGlareButtonOnBitmap;
+    private Bitmap mGlareButtonOffBitmap;
+    private boolean updateGlareRemovalButton = false;
+    private Matrix mDisplaySegPointsMatrix;
+    private Matrix mDisplayMatrixInverse;
+
+    public ImageTrueScanner(Context context) {
+        super(context);
+        init();
+    }
+
+    public ImageTrueScanner(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    public ImageTrueScanner(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public static int[] getDeterminedPoints() {
+        int[] points = new int[mSegPoints.length];
+        for (int i = 0; i < mSegPoints.length; i++) {
+            points[i] = (int)mSegPoints[i];
+        }
+        return points;
+    }
+
+    public static boolean getRemoveGlareButtonStatus() {
+        return mIsGlareButtonPressed;
+    }
+
+    private void init() {
+        mBitmap = MasterImage.getImage().getHighresImage();
+
+        mMarginalGapX = mBitmap.getWidth()/4;
+        mMarginalGapY = mBitmap.getHeight()/4;
+        mGeometry = new GeometryMathUtils.GeometryHolder();
+
+        mSegmentPaint = new Paint();
+        mSegmentPaint.setColor(Color.CYAN);
+        mSegmentPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+        mGlareRemovalTextPaint = new Paint();
+        mGlareRemovalTextPaint.setColor(Color.CYAN);
+        mGlareRemovalTextPaint.setTextSize(35);
+
+        mGrayPaint = new Paint();
+        mGrayPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+        mGrayPaint.setColor(Color.argb(120, 0, 0, 0)); //Gray
+        mIsGlareButtonPressed = false;
+
+
+        Drawable d = getResources().getDrawable(R.drawable.ic_glare_remove_button_on);
+        mGlareButtonOnBitmap = getBitmap(d, 76, 46);
+        d = getResources().getDrawable(R.drawable.ic_glare_remove_button_off);
+        mGlareButtonOffBitmap = getBitmap(d, 76, 46);
+    }
+
+    private Bitmap getBitmap(Drawable d, int width, int height) {
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+        d.draw(canvas);
+        return bitmap;
+    }
+
+    private void checkPointTouch(float x, float y) {
+        for(int i=0; i<POINT_NUMS; i++) {
+            if ( x > mSegPoints[i*2] - CHECK_RADIUS && x < mSegPoints[i*2] + CHECK_RADIUS
+                    && y > mSegPoints[i*2+1] - CHECK_RADIUS && y < mSegPoints[i*2+1] + CHECK_RADIUS) {
+                isTouched[i] = true;
+            }
+        }
+        if( x > mGlareButtonX - CHECK_RADIUS*2 && x < mGlareButtonX + CHECK_RADIUS*2 &&
+               y > mGlareButtonY - CHECK_RADIUS*2 && y < mGlareButtonY + CHECK_RADIUS*2) {
+            mIsGlareButtonPressed = !mIsGlareButtonPressed;
+        }
+    }
+
+    private void moveTouch(float x, float y) {
+        int i;
+        for(i=0; i<POINT_NUMS; i++) {
+            if(isTouched[i]) {
+                mSegPoints[i*2] = (int) x;
+                mSegPoints[i*2+1] = (int) y;
+                break;
+            }
+        }
+        switch(i)
+        {
+            case 0:
+                if(mSegPoints[0] >= mSegPoints[2]-mMarginalGapX)
+                    mSegPoints[0] = mSegPoints[2]-mMarginalGapX;
+                if(mSegPoints[1] >= mSegPoints[7]-mMarginalGapY)
+                    mSegPoints[1] = mSegPoints[7]-mMarginalGapY;
+                if(mSegPoints[0] < mBitmapBound.left) mSegPoints[0] = (int)mBitmapBound.left;
+                if(mSegPoints[1] < mBitmapBound.top) mSegPoints[1] = (int)mBitmapBound.top;
+                break;
+            case 1:
+                if(mSegPoints[2] <= mSegPoints[0]+mMarginalGapX)
+                    mSegPoints[2] = mSegPoints[0]+mMarginalGapX;
+                if(mSegPoints[3] >= mSegPoints[5]-mMarginalGapY)
+                    mSegPoints[3] = mSegPoints[5]-mMarginalGapY;
+                if(mSegPoints[2] > mBitmapBound.right) mSegPoints[2] = (int)mBitmapBound.right;
+                if(mSegPoints[3] < mBitmapBound.top) mSegPoints[3] = (int)mBitmapBound.top;
+                break;
+            case 2:
+                if(mSegPoints[4] <= mSegPoints[6]+mMarginalGapX)
+                    mSegPoints[4] = mSegPoints[6]+mMarginalGapX;
+                if(mSegPoints[5] <= mSegPoints[3]+mMarginalGapY)
+                    mSegPoints[5] = mSegPoints[3]+mMarginalGapY;
+                if(mSegPoints[4] > mBitmapBound.right) mSegPoints[4] = (int)mBitmapBound.right;
+                if(mSegPoints[5] > mBitmapBound.bottom) mSegPoints[5] = (int)mBitmapBound.bottom;
+                break;
+            case 3:
+                if(mSegPoints[6] >= mSegPoints[4]-mMarginalGapX)
+                    mSegPoints[6] = mSegPoints[4]-mMarginalGapX;
+                if(mSegPoints[7] <= mSegPoints[1]+mMarginalGapY)
+                    mSegPoints[7] = mSegPoints[1]+mMarginalGapY;
+                if(mSegPoints[6] < mBitmapBound.left) mSegPoints[6] = (int)mBitmapBound.left;
+                if(mSegPoints[7] > mBitmapBound.bottom) mSegPoints[7] = (int)mBitmapBound.bottom;
+                break;
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        float x = event.getX();
+        float y = event.getY();
+
+        switch (event.getActionMasked()) {
+            case (MotionEvent.ACTION_DOWN):
+                checkPointTouch(x, y);
+            case (MotionEvent.ACTION_MOVE):
+                moveTouch(x,y);
+                break;
+            case (MotionEvent.ACTION_UP):
+                for(int i=0; i<POINT_NUMS; i++) {
+                    isTouched[i] = false;
+                }
+                break;
+        }
+
+        invalidate();
+        return true;
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        updateMatrix(w,h,oldw, oldh);
+        mDisplaySegPointsMatrix.mapPoints(mSegPoints);
+        getBitmapBound();
+        updateGlareRemovalButton = true;
+    }
+
+    private void updateMatrix(int w, int h, int oldw, int oldh) {
+        if (mBitmap == null) {
+            return;
+        }
+        Resources res = getContext().getResources();
+        int panelHeight =  res.getDimensionPixelOffset(R.dimen.category_actionbar_panel_height);
+        mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
+                mBitmap.getWidth(), mBitmap.getHeight(), w, h - panelHeight);
+        mDisplaySegPointsMatrix = GeometryMathUtils.getSegMatrix(mGeometry, mBitmap.getWidth(),
+                mBitmap.getHeight(), w, h - panelHeight, oldw, oldh- panelHeight);
+        mDisplayMatrixInverse = new Matrix();
+        mDisplayMatrixInverse.reset();
+        if (!mDisplaySegPointsMatrix.invert(mDisplayMatrixInverse)) {
+            Log.w(TAG, "could not invert display matrix");
+            mDisplayMatrixInverse = null;
+        }
+    }
+
+    private void getBitmapBound() {
+        mBitmapBound.left = 0;
+        mBitmapBound.right = mBitmap.getWidth();
+        mBitmapBound.top = 0;
+        mBitmapBound.bottom = mBitmap.getHeight();
+        mDisplayMatrix.mapRect(mBitmapBound);
+    }
+
+    public void setDetectedPoints(int[] pts, int width, int height) {
+        synchronized (this) {
+            mDetectedPoints = new int[10];
+            for (int i = 0; i < 8; i++) {
+                mDetectedPoints[i] = pts[i];
+            }
+            mDetectedPoints[8] = width;
+            mDetectedPoints[9] = height;
+        }
+        isDetectedPointsApplied = false;
+        invalidate();
+    }
+
+    private int[] getDetectedPoints() {
+        synchronized (this) {
+            return mDetectedPoints;
+        }
+    }
+
+    private void getInitialInput() {
+        int[] points = getDetectedPoints();
+        if (points == null) {
+            mSegPoints[0] = (int) (mBitmapBound.centerX() - mBitmapBound.width()/4);
+            mSegPoints[1] = (int) (mBitmapBound.centerY() - mBitmapBound.height()/4);
+            mSegPoints[2] = (int) (mBitmapBound.centerX() + mBitmapBound.width()/4);
+            mSegPoints[3] = (int) (mBitmapBound.centerY() - mBitmapBound.height()/4);
+            mSegPoints[4] = (int) (mBitmapBound.centerX() + mBitmapBound.width()/4);
+            mSegPoints[5] = (int) (mBitmapBound.centerY() + mBitmapBound.height()/4);
+            mSegPoints[6] = (int) (mBitmapBound.centerX() - mBitmapBound.width()/4);
+            mSegPoints[7] = (int) (mBitmapBound.centerY() + mBitmapBound.height()/4);
+        } else {
+            float xScale = mBitmapBound.width()/points[8];
+            float yScale = mBitmapBound.height()/points[9];
+            mSegPoints[0] = (int) (mBitmapBound.left + points[0]*xScale);
+            mSegPoints[1] = (int) (mBitmapBound.top + points[1]*yScale);
+            mSegPoints[2] = (int) (mBitmapBound.left + points[2]*xScale);
+            mSegPoints[3] = (int) (mBitmapBound.top + points[3]*yScale);
+            mSegPoints[4] = (int) (mBitmapBound.left + points[4]*xScale);
+            mSegPoints[5] = (int) (mBitmapBound.top + points[5]*yScale);
+            mSegPoints[6] = (int) (mBitmapBound.left + points[6]*xScale);
+            mSegPoints[7] = (int) (mBitmapBound.top + points[7]*yScale);
+        }
+        mSegPoints[8] = (int)mBitmapBound.width();
+        mSegPoints[9] = (int)mBitmapBound.height();
+        mSegPoints[10] = (int)mBitmapBound.left;
+        mSegPoints[11] = (int)mBitmapBound.top;
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if(mBitmap == null)
+            return;
+        toggleComparisonButtonVisibility();
+
+        if(mDisplayMatrix == null || mDisplaySegPointsMatrix == null
+                || mDisplayMatrixInverse == null) {
+            mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry,
+                    mBitmap.getWidth(), mBitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
+            mDisplaySegPointsMatrix = GeometryMathUtils.getSegMatrix(mGeometry,
+                    mBitmap.getWidth(), mBitmap.getHeight(), canvas.getWidth(),
+                    canvas.getHeight(),canvas.getWidth(), canvas.getHeight());
+            mDisplayMatrixInverse = new Matrix();
+            mDisplayMatrixInverse.reset();
+            if (!mDisplaySegPointsMatrix.invert(mDisplayMatrixInverse)) {
+                Log.w(TAG, "could not invert display matrix");
+                mDisplayMatrixInverse = null;
+                return;
+            }
+            getBitmapBound();
+        }
+        if(!isDetectedPointsApplied) {
+            getInitialInput();
+            isDetectedPointsApplied = true;
+        }
+        canvas.drawBitmap(mBitmap, mDisplayMatrix, null);
+        if(mIsCordsUIShowing) {
+            drawSegments(canvas);
+        }
+        drawGlareRemovalButton(canvas);
+    }
+
+    public void setCordsUI(boolean enable) {
+        mIsCordsUIShowing = enable;
+    }
+
+    public static boolean getCordsUIState() {
+        return mIsCordsUIShowing;
+    }
+
+    private void drawGlareRemovalButton(Canvas canvas) {
+        if(mGlareButtonX == -1000 && mGlareButtonY == -1000 || updateGlareRemovalButton) {
+            mGlareButtonX = canvas.getWidth()/2;
+            mGlareButtonY = canvas.getHeight()*1/5;
+            updateGlareRemovalButton = false;
+        }
+        RectF rectF = new RectF();
+        Bitmap bitmap;
+        if(mIsGlareButtonPressed) {
+            bitmap = mGlareButtonOnBitmap;
+        } else {
+            bitmap = mGlareButtonOffBitmap;
+        }
+        rectF.left = mGlareButtonX - bitmap.getWidth()/2;
+        rectF.right = mGlareButtonX + bitmap.getWidth()/2;
+        rectF.top = mGlareButtonY - bitmap.getHeight()/2;
+        rectF.bottom = mGlareButtonY + bitmap.getHeight()/2;
+        canvas.drawBitmap(bitmap, null, rectF, null);
+        canvas.drawText(getResources().getString(R.string.truescanner_remove_glare),
+                mGlareButtonX + bitmap.getWidth()/2+RADIUS, mGlareButtonY + bitmap.getHeight() / 4, mGlareRemovalTextPaint);
+    }
+
+    private void drawSegments(Canvas canvas) {
+        Path path = new Path();
+        path.moveTo(mBitmapBound.left, mBitmapBound.top);
+        path.lineTo(mSegPoints[0], mSegPoints[1]);
+        path.lineTo(mSegPoints[2], mSegPoints[3]);
+        path.lineTo(mBitmapBound.right, mBitmapBound.top);
+        path.lineTo(mBitmapBound.left, mBitmapBound.top);
+        canvas.drawPath(path, mGrayPaint);
+        path.reset();
+        path.moveTo(mBitmapBound.right, mBitmapBound.top);
+        path.lineTo(mSegPoints[2], mSegPoints[3]);
+        path.lineTo(mSegPoints[4], mSegPoints[5]);
+        path.lineTo(mBitmapBound.right, mBitmapBound.bottom);
+        path.lineTo(mBitmapBound.right, mBitmapBound.top);
+        canvas.drawPath(path, mGrayPaint);
+        path.reset();
+        path.moveTo(mBitmapBound.right, mBitmapBound.bottom);
+        path.lineTo(mSegPoints[4], mSegPoints[5]);
+        path.lineTo(mSegPoints[6], mSegPoints[7]);
+        path.lineTo(mBitmapBound.left, mBitmapBound.bottom);
+        path.lineTo(mBitmapBound.right, mBitmapBound.bottom);
+        canvas.drawPath(path, mGrayPaint);
+        path.reset();
+        path.moveTo(mBitmapBound.left, mBitmapBound.bottom);
+        path.lineTo(mSegPoints[6], mSegPoints[7]);
+        path.lineTo(mSegPoints[0], mSegPoints[1]);
+        path.lineTo(mBitmapBound.left, mBitmapBound.top);
+        path.lineTo(mBitmapBound.left, mBitmapBound.bottom);
+        canvas.drawPath(path, mGrayPaint);
+
+        for (int i = 0; i < POINT_NUMS; i++) {
+            canvas.drawCircle(mSegPoints[i * 2], mSegPoints[i * 2 + 1], RADIUS, mSegmentPaint);
+        }
+        canvas.drawLine(mSegPoints[0], mSegPoints[1], mSegPoints[2], mSegPoints[3], mSegmentPaint);
+        canvas.drawLine(mSegPoints[2], mSegPoints[3], mSegPoints[4], mSegPoints[5], mSegmentPaint);
+        canvas.drawLine(mSegPoints[4], mSegPoints[5], mSegPoints[6], mSegPoints[7], mSegmentPaint);
+        canvas.drawLine(mSegPoints[0], mSegPoints[1], mSegPoints[6], mSegPoints[7], mSegmentPaint);
+    }
+
+    public void setEditor(TrueScannerEditor editor) {
+        mEditor = editor;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
index f6b97f1..f71b264 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java
@@ -16,8 +16,12 @@
 
 package com.android.gallery3d.filtershow.imageshow;
 
+import java.util.List;
+import java.util.Vector;
+
 import android.animation.Animator;
 import android.animation.ValueAnimator;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
@@ -25,14 +29,19 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.net.Uri;
+import android.util.Log;
+import android.util.Size;
 
 import com.android.gallery3d.exif.ExifTag;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.cache.BitmapCache;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.category.WaterMarkView;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTruePortraitFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
 import com.android.gallery3d.filtershow.history.HistoryItem;
@@ -44,17 +53,15 @@
 import com.android.gallery3d.filtershow.pipeline.SharedBuffer;
 import com.android.gallery3d.filtershow.pipeline.SharedPreset;
 import com.android.gallery3d.filtershow.state.StateAdapter;
-
-import java.util.List;
-import java.util.Vector;
+import com.android.gallery3d.filtershow.tools.DualCameraEffect;
+import com.android.gallery3d.util.GDepth;
 
 public class MasterImage implements RenderingRequestCaller {
-
-    private static final String LOGTAG = "MasterImage";
+    private static final String TAG = "MasterImage";
     private boolean DEBUG  = false;
     private static final boolean DISABLEZOOM = false;
     public static final int SMALL_BITMAP_DIM = 160;
-    public static final int MAX_BITMAP_DIM = 900;
+    public static final int MAX_BITMAP_DIM = 1280;
     private static MasterImage sMasterImage = null;
 
     private boolean mSupportsHighRes = false;
@@ -72,6 +79,7 @@
     private Bitmap mOriginalBitmapLarge = null;
     private Bitmap mOriginalBitmapHighres = null;
     private Bitmap mTemporaryThumbnail = null;
+
     private int mOrientation;
     private Rect mOriginalBounds;
     private final Vector<ImageShow> mLoadListeners = new Vector<ImageShow>();
@@ -86,6 +94,10 @@
     private int mShadowMargin = 15; // not scaled, fixed in the asset
     private Rect mPartialBounds = new Rect();
 
+    private Bitmap mFusionUnderlay = null;
+    private Rect mImageBounds = null;
+    private Rect mFusionBounds = null;
+
     private ValueAnimator mAnimator = null;
     private float mMaskScale = 1;
     private boolean mOnGoingNewLookAnimation = false;
@@ -103,6 +115,7 @@
     private FilterShowActivity mActivity = null;
 
     private Vector<ImageShow> mObservers = new Vector<ImageShow>();
+    private WaterMarkView mWaterMark = null;
     private FilterRepresentation mCurrentFilterRepresentation;
 
     private float mScaleFactor = 1.0f;
@@ -121,6 +134,12 @@
 
     // TODO: remove singleton
     public static void setMaster(MasterImage master) {
+        if((master == null || master != sMasterImage)
+                && sMasterImage != null) {
+            // clearing singleton, clean up resources
+            // in old instance
+            sMasterImage.freeResources();
+        }
         sMasterImage = master;
     }
 
@@ -131,6 +150,73 @@
         return sMasterImage;
     }
 
+    private void freeResources() {
+        if(mOriginalBitmapSmall != null) {
+            mOriginalBitmapSmall.recycle();
+        }
+        mOriginalBitmapSmall = null;
+
+        if(mOriginalBitmapLarge != null) {
+            mOriginalBitmapLarge.recycle();
+        }
+        mOriginalBitmapLarge = null;
+
+        if(mOriginalBitmapHighres != null) {
+            mOriginalBitmapHighres.recycle();
+        }
+        mOriginalBitmapHighres = null;
+
+        if(mTemporaryThumbnail != null) {
+            mTemporaryThumbnail.recycle();
+        }
+        mTemporaryThumbnail = null;
+
+        if(mGeometryOnlyBitmap != null) {
+            mGeometryOnlyBitmap.recycle();
+        }
+        mGeometryOnlyBitmap = null;
+
+        if(mFiltersOnlyBitmap != null) {
+            mFiltersOnlyBitmap.recycle();
+        }
+        mFiltersOnlyBitmap = null;
+
+        if(mPartialBitmap != null) {
+            mPartialBitmap.recycle();
+        }
+        mPartialBitmap = null;
+
+        if(mHighresBitmap != null) {
+            mHighresBitmap.recycle();
+        }
+        mHighresBitmap = null;
+
+        if(mPreviousImage != null) {
+            mPreviousImage.recycle();
+        }
+        mPreviousImage = null;
+
+        if(mFusionUnderlay != null) {
+            mFusionUnderlay.recycle();
+        }
+        mFusionUnderlay = null;
+
+        if(mBitmapCache != null) {
+            mBitmapCache.clear();
+        }
+
+        mPreviewBuffer.reset();
+
+        if (mGDepthParser != null) mGDepthParser = null;
+        if (mGDepthImage != null) mGDepthImage = null;
+        if (mEffect != null) {
+            mEffect.release();
+            mEffect = null;
+            mTargetHeight = 0;
+            mTargetWidth = 0;
+        }
+    }
+
     public Bitmap getOriginalBitmapSmall() {
         return mOriginalBitmapSmall;
     }
@@ -195,6 +281,24 @@
         }
     };
 
+    public static Bitmap convertToEvenNumberWidthImage(Bitmap bmp) {
+        Bitmap retBmp = null;
+        if (bmp != null) {
+            int w = bmp.getWidth();
+            int h = bmp.getHeight();
+            boolean bWidthIsEven = (w & 0x01) == 0;
+            boolean bHeightIsEven = (h & 0x01) == 0;
+            Log.v(TAG, "ori bitmap w="+w+" h="+h);
+            if( !bWidthIsEven || !bHeightIsEven){
+                w = w - (w & 0x01);
+                h = h - (h & 0x01);
+                retBmp = Bitmap.createBitmap(bmp, 0, 0, w, h);
+                Log.v(TAG, "new bitmap w="+retBmp.getWidth()+" h="+retBmp.getHeight());
+            }
+        }
+        return retBmp;
+    }
+
     public boolean loadBitmap(Uri uri, int size) {
         setUri(uri);
         mEXIF = ImageLoader.getExif(getActivity(), uri);
@@ -203,6 +307,14 @@
         mOriginalBitmapLarge = ImageLoader.loadOrientedConstrainedBitmap(uri, mActivity,
                 Math.min(MAX_BITMAP_DIM, size),
                 mOrientation, originalBounds);
+        // Force bitmap width and height to even number for beautification algo.
+        Bitmap tempBmp = convertToEvenNumberWidthImage(mOriginalBitmapLarge);
+        if(tempBmp != null && mOriginalBitmapLarge != null) {
+            if(!mOriginalBitmapLarge.isRecycled() && mOriginalBitmapLarge != tempBmp) {
+                mOriginalBitmapLarge.recycle();
+            }
+            mOriginalBitmapLarge = tempBmp;
+        }
         setOriginalBounds(originalBounds);
         if (mOriginalBitmapLarge == null) {
             return false;
@@ -211,6 +323,9 @@
         int sh = (int) (sw * (float) mOriginalBitmapLarge.getHeight() / mOriginalBitmapLarge
                 .getWidth());
         mOriginalBitmapSmall = Bitmap.createScaledBitmap(mOriginalBitmapLarge, sw, sh, true);
+        Log.d(TAG, "MasterImage.loadBitmap(): OriginalBitmapLarge.WH is (" + mOriginalBitmapLarge.getWidth() + ", "
+                + mOriginalBitmapLarge.getHeight() + "), OriginalBitmapSmall.WH is (" + sw + ", " + sh + "), originalBounds is "
+                + originalBounds.toString());
         mZoomOrientation = mOrientation;
         warnListeners();
         return true;
@@ -231,6 +346,14 @@
         mObservers.remove(observer);
     }
 
+    public void addWaterMark(WaterMarkView waterMarkView) {
+        mWaterMark = waterMarkView;
+    }
+
+    public void removeWaterMark() {
+        mWaterMark = null;
+    }
+
     public void setActivity(FilterShowActivity activity) {
         mActivity = activity;
     }
@@ -254,6 +377,12 @@
     public synchronized void setPreset(ImagePreset preset,
                                        FilterRepresentation change,
                                        boolean addToHistory) {
+        setPreset(preset, change, addToHistory, true);
+    }
+
+    public synchronized void setPreset(ImagePreset preset,
+                                       FilterRepresentation change,
+                                       boolean addToHistory, boolean updateCategory) {
         if (DEBUG) {
             preset.showFilters();
         }
@@ -265,15 +394,24 @@
         }
         updatePresets(true);
         resetGeometryImages(false);
-        mActivity.updateCategories();
+        if (updateCategory) {
+            mActivity.updateCategories();
+        }
     }
 
     public void onHistoryItemClick(int position) {
+        onHistoryItemClick(position, true);
+    }
+
+    public void onHistoryItemClick(int position, boolean updateCategory) {
         HistoryItem historyItem = mHistory.getItem(position);
         // We need a copy from the history
+        if (historyItem == null) {
+            return;
+        }
         ImagePreset newPreset = new ImagePreset(historyItem.getImagePreset());
         // don't need to add it to the history
-        setPreset(newPreset, historyItem.getFilterRepresentation(), false);
+        setPreset(newPreset, historyItem.getFilterRepresentation(), false, updateCategory);
         mHistory.setCurrentPreset(position);
     }
 
@@ -321,6 +459,18 @@
         }
     }
 
+    public synchronized boolean hasFusionApplied() {
+        FilterRepresentation dcRepresentation =
+                mPreset.getFilterWithSerializationName(FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+        FilterRepresentation tpRepresentation =
+                mPreset.getFilterWithSerializationName(FilterTruePortraitFusionRepresentation.SERIALIZATION_NAME);
+        if(dcRepresentation instanceof FilterDualCamFusionRepresentation ||
+                tpRepresentation instanceof FilterTruePortraitFusionRepresentation) {
+            return true;
+        }
+        return false;
+    }
+
     public SharedBuffer getPreviewBuffer() {
         return mPreviewBuffer;
     }
@@ -415,7 +565,7 @@
         if (mAnimator != null) {
             mAnimator.cancel();
             if (mCurrentLookAnimation == ROTATE_ANIMATION) {
-                mCurrentAnimRotationStartValue += 90;
+                mCurrentAnimRotationStartValue -= 90;
             }
         } else {
             resetAnimBitmap();
@@ -428,7 +578,7 @@
         }
         if (newRepresentation instanceof FilterRotateRepresentation) {
             mCurrentLookAnimation = ROTATE_ANIMATION;
-            mAnimator = ValueAnimator.ofFloat(0, 90);
+            mAnimator = ValueAnimator.ofFloat(0, -90);
             mAnimator.setDuration(500);
         }
         if (newRepresentation instanceof FilterMirrorRepresentation) {
@@ -482,6 +632,11 @@
         }
     }
 
+    public void notifyWaterMarks() {
+        if (mWaterMark != null) {
+            mWaterMark.update();
+        }
+    }
     public void resetGeometryImages(boolean force) {
         if (mPreset == null) {
             return;
@@ -594,9 +749,9 @@
                     bitmapToDraw.getWidth(),
                     bitmapToDraw.getHeight());
             scale = mImageShowSize.x / size.width();
-            if (size.width() < size.height()) {
-                scale = mImageShowSize.y / size.height();
-            }
+            float tmp = mImageShowSize.y / size.height();
+            // Choose the smaller one to avoid master image beyound the screen.
+            scale = scale < tmp ? scale : tmp;
             translateX = (mImageShowSize.x - (size.width() * scale)) / 2.0f;
             translateY = (mImageShowSize.y - (size.height() * scale)) / 2.0f;
         } else {
@@ -612,11 +767,11 @@
                 mImageShowSize.x / 2.0f,
                 mImageShowSize.y / 2.0f);
         m.postTranslate(translation.x * getScaleFactor(),
-                        translation.y * getScaleFactor());
+                translation.y * getScaleFactor());
         return m;
     }
 
-    private Matrix getImageToScreenMatrix(boolean reflectRotation) {
+    public Matrix getImageToScreenMatrix(boolean reflectRotation) {
         if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) {
             return new Matrix();
         }
@@ -634,7 +789,7 @@
         return m;
     }
 
-    private Matrix getScreenToImageMatrix(boolean reflectRotation) {
+    public Matrix getScreenToImageMatrix(boolean reflectRotation) {
         Matrix m = getImageToScreenMatrix(reflectRotation);
         Matrix invert = new Matrix();
         m.invert(invert);
@@ -713,15 +868,9 @@
             mBitmapCache.cache(mHighresBitmap);
             mHighresBitmap = request.getBitmap();
             notifyObservers();
+            notifyWaterMarks();
             needsCheckModification = true;
         }
-        if (needsCheckModification) {
-            mActivity.enableSave(hasModifications());
-        }
-    }
-
-    public static void reset() {
-        sMasterImage = null;
     }
 
     public float getScaleFactor() {
@@ -833,4 +982,82 @@
     public boolean hasTinyPlanet() {
         return mPreset.contains(FilterRepresentation.TYPE_TINYPLANET);
     }
+
+    public void setFusionUnderlay(Bitmap underlay) {
+        mFusionUnderlay = underlay;
+    }
+
+    public Bitmap getFusionUnderlay() {
+        return mFusionUnderlay;
+    }
+
+    public void setFusionBounds(Canvas canvas, RectF bounds) {
+        if(mFusionBounds == null) mFusionBounds = new Rect();
+        bounds.roundOut(mFusionBounds);
+    }
+
+    public Rect getFusionBounds() {
+        return mFusionBounds;
+    }
+
+    public void setImageBounds(Canvas canvas, Rect bounds) {
+        mImageBounds = bounds;
+    }
+
+    public Rect getImageBounds() {
+        return mImageBounds;
+    }
+
+    private GDepth.Parser mGDepthParser;
+    private GDepth.Image mGDepthImage;
+    private DualCameraEffect mEffect;
+    private int mTargetWidth;
+    private int mTargetHeight;
+
+    public boolean parseDepthMap(Context context, Uri uri) {
+        if (mGDepthImage != null && mGDepthImage.valid()) return true;
+        if (mGDepthParser == null) {
+            mGDepthParser = new GDepth.Parser();
+            mGDepthParser.parse(context, uri);
+        }
+        return mGDepthParser.valid();
+    }
+
+    public DualCameraEffect getDualCameraEffect(int targetWidth, int targetHeight) {
+        if (targetWidth == mTargetWidth && targetHeight == mTargetHeight && mEffect != null) {
+            Log.d(TAG, "reuse effect");
+            return mEffect;
+        }
+        if (mGDepthImage == null) {
+            if (mGDepthParser == null || !mGDepthParser.valid()) {
+                Log.e(TAG, "parser not valid");
+                return null;
+            }
+            mGDepthImage = mGDepthParser.decode();
+            if (mGDepthImage == null) {
+                Log.e(TAG, "can't decode image");
+                return null;
+            }
+            mGDepthParser = null;
+        }
+        if (mEffect == null) {
+            mEffect = DualCameraEffect.getInstance();
+        }
+        mEffect.release();
+
+        int[] roi = mGDepthImage.roi;
+        if (targetWidth > roi[2]) targetWidth = roi[2];
+        if (targetHeight > roi[3]) targetHeight = roi[3];
+
+        Log.d(TAG, "init effect: " + targetWidth + "x" + targetHeight);
+        boolean result = mEffect.initialize(mGDepthImage.bitmap, mGDepthImage.depthMap,
+                mGDepthImage.roi, targetWidth, targetHeight, 1.0f);
+        if (result) {
+            mTargetWidth = targetWidth;
+            mTargetHeight = targetHeight;
+            return mEffect;
+        }
+        Log.d(TAG, "init failed");
+        return null;
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/info/HistogramView.java b/src/com/android/gallery3d/filtershow/info/HistogramView.java
index 99cf235..7b7edb4 100644
--- a/src/com/android/gallery3d/filtershow/info/HistogramView.java
+++ b/src/com/android/gallery3d/filtershow/info/HistogramView.java
@@ -93,12 +93,13 @@
 
         mPaint.reset();
         mPaint.setAntiAlias(true);
-        mPaint.setARGB(100, 255, 255, 255);
+        mPaint.setARGB(100, 0, 0, 0);
         mPaint.setStrokeWidth((int) Math.ceil(wl));
 
         // Draw grid
         mPaint.setStyle(Paint.Style.STROKE);
         canvas.drawRect(dx, 0, dx + w, h, mPaint);
+        mPaint.setARGB(100, 200, 200, 200);
         canvas.drawLine(dx + w / 3, 0, dx + w / 3, h, mPaint);
         canvas.drawLine(dx + 2 * w / 3, 0, dx + 2 * w / 3, h, mPaint);
 
diff --git a/src/com/android/gallery3d/filtershow/info/InfoPanel.java b/src/com/android/gallery3d/filtershow/info/InfoPanel.java
index 1d8751d..700291a 100644
--- a/src/com/android/gallery3d/filtershow/info/InfoPanel.java
+++ b/src/com/android/gallery3d/filtershow/info/InfoPanel.java
@@ -17,28 +17,28 @@
 package com.android.gallery3d.filtershow.info;
 
 import android.graphics.Bitmap;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
-import androidx.fragment.app.DialogFragment;
 import android.text.Html;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
-import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.exif.ExifInterface;
 import com.android.gallery3d.exif.ExifTag;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
+import com.android.gallery3d.ui.BaseDialogFragment;
 
 import java.util.List;
 
-public class InfoPanel extends DialogFragment {
+public class InfoPanel extends BaseDialogFragment {
     public static final String FRAGMENT_TAG = "InfoPanel";
     private static final String LOGTAG = FRAGMENT_TAG;
     private LinearLayout mMainView;
@@ -80,6 +80,7 @@
 
         HistogramView histogramView = (HistogramView) mMainView.findViewById(R.id.histogramView);
         histogramView.setBitmap(bitmap);
+        histogramView.setBackgroundColor(Color.DKGRAY);
 
         Uri uri = MasterImage.getImage().getUri();
         String path = ImageLoader.getLocalPathFromUri(getActivity(), uri);
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java
new file mode 100644
index 0000000..9a53a93
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaAdapter.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.MediaStore;
+import androidx.cursoradapter.widget.CursorAdapter;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.AbsListView.RecyclerListener;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.android.gallery3d.filtershow.mediapicker.imageloader.ImageLoaderStub;
+import org.codeaurora.gallery.R;
+
+/**
+ * Adapter for display media item list.
+ */
+public class MediaAdapter extends CursorAdapter implements RecyclerListener {
+    private ImageLoaderStub mMediaImageLoader;
+    private Uri mMediaSelected;
+    private int mItemHeight = 0;
+    private int mNumColumns = 0;
+    private RelativeLayout.LayoutParams mImageViewLayoutParams;
+    private List<SelectedImageView> mImageViewSelected = new ArrayList<SelectedImageView>();
+
+    public MediaAdapter(Context context, Cursor c, int flags,
+                        ImageLoaderStub mediaImageLoader) {
+        this(context, c, flags, null, mediaImageLoader);
+    }
+
+    public MediaAdapter(Context context, Cursor c, int flags,
+                        Uri mediaSelected, ImageLoaderStub mediaImageLoader) {
+        super(context, c, flags);
+        mMediaSelected = mediaSelected;
+        mMediaImageLoader = mediaImageLoader;
+        mImageViewLayoutParams = new RelativeLayout.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+    }
+
+    @Override
+    public void bindView(View view, Context context, Cursor cursor) {
+        final SelectedImageView imageView = (SelectedImageView) view.getTag();
+        final Uri uri;
+        uri = getPhotoUri(cursor);
+
+        boolean isSelected = isSelected(uri);
+        imageView.setSelected(isSelected);
+        if (isSelected) {
+            mImageViewSelected.add(imageView);
+        }
+        mMediaImageLoader.displayImage(uri, imageView);
+    }
+
+    @Override
+    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
+        View root = View
+                .inflate(context, R.layout.mediapicker_list_item, null);
+        SelectedImageView imageView = (SelectedImageView) root.findViewById(R.id.thumbnail);
+
+        imageView.setLayoutParams(mImageViewLayoutParams);
+        // Check the height matches our calculated column width
+        if (imageView.getLayoutParams().height != mItemHeight) {
+            imageView.setLayoutParams(mImageViewLayoutParams);
+        }
+        root.setTag(imageView);
+        return root;
+    }
+
+    public Uri getPhotoUri(Cursor cursor) {
+        String id = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
+        return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
+    }
+
+    /**
+     * Check media uri is selected or not.
+     *
+     * @param uri Uri of media item (photo, video)
+     * @return true if selected, false otherwise.
+     */
+    public boolean isSelected(Uri uri) {
+        if (uri == null)
+            return false;
+        if (mMediaSelected != null) {
+            if (mMediaSelected.equals(uri))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * If item selected then change to unselected and unselected to selected.
+     *
+     * @param item Item to update.
+     */
+    public void updateMediaSelected(Uri item,
+                                    SelectedImageView selImageView) {
+        if (mMediaSelected == null || !mMediaSelected.equals(item)) {
+            for (SelectedImageView picker : this.mImageViewSelected) {
+                picker.setSelected(false);
+            }
+            this.mImageViewSelected.clear();
+
+            mMediaSelected = item;
+            selImageView.setSelected(true);
+            this.mImageViewSelected.add(selImageView);
+        }
+    }
+
+    public void setMediaSelected(Uri item) {
+        mMediaSelected = item;
+    }
+
+    // set numcols
+    public void setNumColumns(int numColumns) {
+        mNumColumns = numColumns;
+    }
+
+    public int getNumColumns() {
+        return mNumColumns;
+    }
+
+    // set photo item height
+    public void setItemHeight(int height) {
+        if (height == mItemHeight) {
+            return;
+        }
+        mItemHeight = height;
+        mImageViewLayoutParams.height = height;
+        mImageViewLayoutParams.width = height;
+        notifyDataSetChanged();
+    }
+
+    @Override
+    public void onMovedToScrapHeap(View view) {
+        SelectedImageView imageView = (SelectedImageView) view
+                .findViewById(R.id.thumbnail);
+        mImageViewSelected.remove(imageView);
+    }
+
+    public void onDestroyView() {
+        mImageViewSelected.clear();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java
new file mode 100644
index 0000000..7fa96fa
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaPicker.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Build;
+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.ImageButton;
+import android.widget.LinearLayout;
+
+import com.android.photos.views.HeaderGridView;
+
+import org.codeaurora.gallery.R;
+
+public class MediaPicker extends ViewGroup {
+
+    private LinearLayout mSelStrip;
+    private LinearLayout mSlideStrip;
+    private HeaderGridView mGridView;
+    private ImageButton mArrow;
+
+    private boolean mIsFullScreen, mLayoutChanged;
+    private int mCurrentDesiredHeight;
+
+    private final Handler mHandler = new Handler();
+    private int mDefaultGridHeight;
+    private TouchHandler mTouchHandler;
+
+    static Context mContext;
+
+    public MediaPicker(final Context context, final AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        mIsFullScreen = true;
+    }
+
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSlideStrip = (LinearLayout) findViewById(R.id.mediapicker_slidestrip);
+        mSelStrip = (LinearLayout) findViewById(R.id.mediapicker_tabstrip);
+        mGridView = (HeaderGridView) findViewById(R.id.grid);
+        mArrow = (ImageButton) findViewById(R.id.arrow);
+        mTouchHandler = new TouchHandler();
+        mArrow.setOnTouchListener(mTouchHandler);
+
+        addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            private boolean mLandMode = 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 newLandMode = isLandscapeMode();
+                if (mLandMode != newLandMode) {
+                    mLandMode = newLandMode;
+                    mLayoutChanged = true;
+                    setupFullScreen(mIsFullScreen, false);
+                }
+            }
+        });
+    }
+
+    @Override
+    protected void onLayout(final boolean changed, final int left, final int top, final int right,
+                            final int bottom) {
+        int y = bottom;
+        final int width = right - left;
+        final int selHight = mSelStrip.getMeasuredHeight();
+        mSelStrip.layout(0, y - selHight, width, y);
+        y -= selHight;
+
+        final int gridHeight = mGridView.getMeasuredHeight();
+        mGridView.layout(0, y - gridHeight, width, y);
+        y -= gridHeight;
+
+        mSlideStrip.layout(0, y - mSlideStrip.getMeasuredHeight(), width, y);
+    }
+
+    @Override
+    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
+        int requestedHeight = MeasureSpec.getSize(heightMeasureSpec);
+        measureChild(mSelStrip, widthMeasureSpec, heightMeasureSpec);
+
+        int selStripHeight = mSelStrip.getMeasuredHeight();
+        measureChild(mSlideStrip, widthMeasureSpec, heightMeasureSpec);
+        int slideHeight = mSlideStrip.getMeasuredHeight();
+
+        final int gridAdjustedHeight = mCurrentDesiredHeight - selStripHeight - slideHeight;
+        int gridHeight;
+        if (gridAdjustedHeight < 0)
+            gridHeight = 0;
+        else if (gridAdjustedHeight < mDefaultGridHeight)
+            gridHeight = mDefaultGridHeight;
+        else
+            gridHeight = gridAdjustedHeight;
+
+        int gridHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+                gridHeight, MeasureSpec.EXACTLY);
+        measureChild(mGridView, widthMeasureSpec, gridHeightMeasureSpec);
+        setMeasuredDimension(mGridView.getMeasuredWidth(), requestedHeight);
+    }
+
+    public void setupFullScreen(final boolean isFullScreen, final boolean animate) {
+        if (isFullScreen == mIsFullScreen && !mLayoutChanged) {
+            return;
+        }
+
+        mIsFullScreen = isFullScreen;
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                setViewHeight(animate);
+            }
+        });
+    }
+
+    private void setViewHeight(boolean animate) {
+        final int startHeight = mCurrentDesiredHeight;
+        int height = getContext().getResources().getDisplayMetrics().heightPixels;
+        if (!mIsFullScreen) {
+            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(500);
+            startAnimation(animation);
+        } else {
+            mCurrentDesiredHeight = height;
+        }
+        if (mIsFullScreen)
+            mArrow.setImageResource(R.drawable.arrow_down);
+        else
+            mArrow.setImageResource(R.drawable.arrow);
+        requestLayout();
+    }
+
+    private int measureHeight() {
+        final int measureSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 1, MeasureSpec.AT_MOST);
+        measureChild(mSelStrip, measureSpec, measureSpec);
+        measureChild(mSlideStrip, measureSpec, measureSpec);
+        if (isLandscapeMode())
+            mDefaultGridHeight = getResources().getDimensionPixelSize(
+                    R.dimen.mediapicker_land_height);
+        else
+            mDefaultGridHeight = getResources().getDimensionPixelSize(
+                    R.dimen.mediapicker_default_height);
+        return mDefaultGridHeight + mSelStrip.getMeasuredHeight() + mSlideStrip.getMeasuredHeight();
+    }
+
+    private boolean isLandscapeMode() {
+        return mContext.getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE;
+    }
+
+    private class TouchHandler implements OnTouchListener {
+        private boolean mMoved = false;
+        private MotionEvent mDownEvent;
+        private static final float DIRECTION_RATIO = 1.1f;
+        private static final int TOUCH_THRESHOLD = 450;
+        private static final int TOUCH_SLOP = 24;
+
+
+        TouchHandler() {
+        }
+
+        boolean checkMoved(final MotionEvent mv) {
+            final float dx = mDownEvent.getRawX() - mv.getRawX();
+            final float dy = mDownEvent.getRawY() - mv.getRawY();
+            if (Math.abs(dy) > TOUCH_SLOP &&
+                    (Math.abs(dy) / Math.abs(dx)) > DIRECTION_RATIO) {
+                return true;
+            }
+            return false;
+        }
+
+        @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 dy = motionEvent.getRawY() - mDownEvent.getRawY();
+                    final float dt =
+                            (motionEvent.getEventTime() - mDownEvent.getEventTime()) / 1000.0f;
+                    final float yVelocity = dy / dt;
+
+                    if (checkMoved(motionEvent)) {
+                        if ((yVelocity + TOUCH_THRESHOLD) < 0 && !mIsFullScreen) {
+                            setupFullScreen(true, true);
+                        } else if ((yVelocity - TOUCH_THRESHOLD) > 0 && mIsFullScreen) {
+                            setupFullScreen(false, true);
+                        }
+                    }
+                    mDownEvent = null;
+                    mMoved = false;
+                    break;
+                }
+                case MotionEvent.ACTION_DOWN: {
+                    mDownEvent = MotionEvent.obtain(motionEvent);
+                    return true;
+                }
+                case MotionEvent.ACTION_MOVE: {
+                    if (mDownEvent == null) {
+                        return mMoved;
+                    }
+                    if (checkMoved(motionEvent)) {
+                        mMoved = true;
+                    }
+                }
+            }
+            return mMoved;
+        }
+    }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java b/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java
new file mode 100644
index 0000000..42a0fb9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/MediaPickerFragment.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.app.Activity;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.provider.MediaStore;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.MediaColumns;
+import androidx.fragment.app.Fragment;
+import androidx.loader.app.LoaderManager;
+import androidx.loader.content.CursorLoader;
+import androidx.loader.content.Loader;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ImageButton;
+
+import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.mediapicker.imageloader.ImageLoaderStub;
+import com.android.photos.views.HeaderGridView;
+
+import org.codeaurora.gallery.R;
+
+/**
+ * Display list of videos, photos from {@link MediaStore} and select one or many
+ * item from list depends on {@link MediaOptions} that passed when open media
+ * picker.
+ */
+public class MediaPickerFragment extends Fragment implements
+        LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
+    private static final String LOADER_EXTRA_URI = "loader_extra_uri";
+    private static final String LOADER_EXTRA_PROJECT = "loader_extra_project";
+    private static final String KEY_GRID_STATE = "grid_state";
+    private static final String KEY_MEDIA_SELECTED = "media_selected";
+    private HeaderGridView mGridView;
+
+    protected ImageLoaderStub mMediaImageLoader;
+    protected Context mContext;
+    protected static Context appContext;
+    protected FilterShowActivity mActivity;
+    protected FilterRepresentation mCntFp, mOldFp;
+
+    private MediaAdapter mMediaAdapter;
+
+    private Bundle mSavedInstanceState;
+    private Uri mMediaSelected;
+    private ImageButton mSelDone, mSelCancel;
+
+    private int mPhotoSize, mPhotoSpacing;
+    private int mIndexPreset;
+    private MediaPicker mMediaPicker;
+
+    public MediaPickerFragment() {
+        mSavedInstanceState = new Bundle();
+    }
+
+    public static MediaPickerFragment newInstance(Context context) {
+        MediaPickerFragment fragment = new MediaPickerFragment();
+        appContext = context;
+        return fragment;
+    }
+
+    @Override
+    public void onAttach(Activity activity) {
+        super.onAttach(activity);
+        mMediaImageLoader = new ImageLoaderStub(appContext);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (savedInstanceState != null) {
+            mMediaSelected = savedInstanceState
+                    .getParcelable(KEY_MEDIA_SELECTED);
+            mSavedInstanceState = savedInstanceState;
+        }
+
+        // get the photo size and spacing
+        mPhotoSize = getResources().getDimensionPixelSize(
+                R.dimen.picker_photo_size);
+        mPhotoSpacing = getResources().getDimensionPixelSize(
+                R.dimen.picker_photo_spacing);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        mMediaPicker = (MediaPicker) inflater.inflate(
+                R.layout.mediapicker_panel,
+                container,
+                false);
+        mSelDone = (ImageButton) mMediaPicker.findViewById(R.id.btn_yes);
+        mSelCancel = (ImageButton) mMediaPicker.findViewById(R.id.btn_no);
+        mSelDone.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mMediaSelected != null) {
+                    mActivity.onMediaPickerResult(mMediaSelected);
+                } else {
+                    mActivity.useFilterRepresentation(mOldFp);
+                    mActivity.onBackPressed();
+                }
+            }
+        });
+        mSelCancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (mOldFp != null)
+                    mActivity.useFilterRepresentation(mOldFp);
+                else
+                    mActivity.setDefaultPreset();
+                mActivity.onBackPressed();
+            }
+        });
+
+        initView(mMediaPicker);
+        mMediaPicker.setupFullScreen(false, true);
+        return mMediaPicker;
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mContext = getActivity();
+        mActivity = (FilterShowActivity) mContext;
+        mOldFp = mActivity.getCurrentPresentation();
+        mIndexPreset = 100;
+        requestPic();
+    }
+
+    public void requestPic() {
+        requestMedia(Images.Media.EXTERNAL_CONTENT_URI,
+                new String[]{MediaColumns._ID});
+    }
+
+    private void requestMedia(Uri uri, String[] projects) {
+        Bundle bundle = new Bundle();
+        bundle.putStringArray(LOADER_EXTRA_PROJECT, projects);
+        bundle.putString(LOADER_EXTRA_URI, uri.toString());
+        getLoaderManager().initLoader(0, bundle, this);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        if (mGridView != null) {
+            mSavedInstanceState.putParcelable(KEY_GRID_STATE,
+                    mGridView.onSaveInstanceState());
+        }
+        mSavedInstanceState.putParcelable(KEY_MEDIA_SELECTED,
+                mMediaSelected);
+        outState.putAll(mSavedInstanceState);
+    }
+
+    @Override
+    public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {
+        Uri uri = Uri.parse(bundle.getString(LOADER_EXTRA_URI));
+        String[] projects = bundle.getStringArray(LOADER_EXTRA_PROJECT);
+        String order = MediaColumns.DATE_ADDED + " DESC";
+        return new CursorLoader(mContext, uri, projects, null, null, order);
+    }
+
+    private void attachData(Cursor cursor) {
+        if (cursor == null || cursor.getCount() <= 0) {
+            switchToError();
+            return;
+        }
+        mGridView.setVisibility(View.VISIBLE);
+        if (mMediaSelected != null) {
+            mMediaSelected = null;
+            mMediaAdapter.setMediaSelected(mMediaSelected);
+        }
+        if (mMediaAdapter == null) {
+            mMediaAdapter = new MediaAdapter(mContext, cursor, 0,
+                     mMediaImageLoader);
+        } else {
+            mMediaAdapter.swapCursor(cursor);
+        }
+        if (mGridView.getAdapter() == null) {
+            mGridView.setAdapter(mMediaAdapter);
+            mGridView.setRecyclerListener(mMediaAdapter);
+        }
+        Parcelable state = mSavedInstanceState.getParcelable(KEY_GRID_STATE);
+        if (state != null) {
+            mGridView.onRestoreInstanceState(state);
+        }
+        mMediaAdapter.notifyDataSetChanged();
+    }
+
+    @Override
+    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
+        attachData(cursor);
+    }
+
+    @Override
+    public void onLoaderReset(Loader<Cursor> loader) {
+        // Preference:http://developer.android.com/guide/components/loaders.html#callback
+        if (mMediaAdapter != null)
+            mMediaAdapter.swapCursor(null);
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position,
+                            long id) {
+        Object object = parent.getAdapter().getItem(position);
+        if (object instanceof Cursor) {
+            Uri uri;
+            uri = getPicUri((Cursor) object);
+
+            if (!uri.equals(mMediaSelected)) {
+                mIndexPreset++;
+                mCntFp = mActivity.createUserPresentaion(uri, mIndexPreset);
+                mActivity.applyCustomFilterRepresentation(mCntFp, mOldFp);
+            }
+
+            SelectedImageView selImageView = (SelectedImageView) view
+                    .findViewById(R.id.thumbnail);
+            mMediaSelected = uri;
+            mMediaAdapter.updateMediaSelected(uri, selImageView);
+        }
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        if (mGridView != null) {
+            mSavedInstanceState.putParcelable(KEY_GRID_STATE,
+                    mGridView.onSaveInstanceState());
+            mGridView = null;
+        }
+        if (mMediaAdapter != null) {
+            mMediaAdapter.onDestroyView();
+        }
+    }
+
+
+    private Uri getPicUri(Cursor cursor) {
+        String id = cursor.getString(cursor.getColumnIndex(MediaColumns._ID));
+        return Uri.withAppendedPath(Images.Media.EXTERNAL_CONTENT_URI, id);
+    }
+
+    private void switchToError() {
+        mGridView.setVisibility(View.GONE);
+        mSelDone.setVisibility(View.GONE);
+        mSelCancel.setVisibility(View.GONE);
+    }
+
+    private void initView(MediaPicker view) {
+        mGridView = (HeaderGridView) view.findViewById(R.id.grid);
+        mGridView.setOnItemClickListener(this);
+
+        mGridView.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+                    @Override
+                    public void onGlobalLayout() {
+                        if (mMediaAdapter != null
+                                && mMediaAdapter.getNumColumns() == 0) {
+                            final int numColumns = (int) Math.floor(mGridView
+                                    .getWidth() / (mPhotoSize + mPhotoSpacing));
+                            if (numColumns > 0) {
+                                final int columnWidth = (mGridView.getWidth() / numColumns)
+                                        - mPhotoSpacing;
+                                mMediaAdapter.setNumColumns(numColumns);
+                                mMediaAdapter.setItemHeight(columnWidth);
+                            }
+                        }
+                    }
+                });
+    }
+
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java b/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java
new file mode 100644
index 0000000..11b4ee6
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/SelectedImageView.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import org.codeaurora.gallery.R;
+
+public class SelectedImageView extends ImageView {
+
+    private boolean sel;
+    private int size = 1;
+    private Paint border;
+
+    public SelectedImageView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        init();
+    }
+
+    public SelectedImageView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+    }
+
+    private void init() {
+        border = new Paint();
+        border.setAntiAlias(true);
+        border.setColor(getResources().getColor(R.color.picker_color));
+        size = getResources().getDimensionPixelSize(
+                R.dimen.picker_border_size);
+    }
+
+    public SelectedImageView(Context context) {
+        super(context);
+        init();
+    }
+
+    public void setSelected(boolean selected) {
+        if (selected != this.sel) {
+            this.sel = selected;
+            invalidate();
+        }
+    }
+
+    public boolean isSelected() {
+        return sel;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        int width = getMeasuredWidth();
+        setMeasuredDimension(width, width);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        if (sel) {
+            canvas.drawRect(0, 0, size, getHeight(), border);
+            canvas.drawRect(getWidth() - size, 0, getWidth(),
+                    getHeight(), border);
+            canvas.drawRect(0, 0, getWidth(), size, border);
+            canvas.drawRect(0, getHeight() - size, getWidth(),
+                    getHeight(), border);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java
new file mode 100644
index 0000000..e9efb55
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageDisplayTask.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.util.Log;
+
+final class ImageDisplayTask implements Runnable {
+
+    private static final String TAG = "ImageDisplayTask";
+
+    private final Bitmap bitmap;
+    private final ImageViewImpl imageView;
+    private final String memoryCacheKey;
+    private final ImageLoaderHandle handle;
+
+    public ImageDisplayTask(Bitmap bitmap, ImageLoaderInfo imageLoadingInfo,
+                            ImageLoaderHandle handle) {
+        this.bitmap = bitmap;
+        imageView = imageLoadingInfo.imageView;
+        memoryCacheKey = imageLoadingInfo.memoryCacheKey;
+        this.handle = handle;
+    }
+
+    @Override
+    public void run() {
+        if (imageView.isRecyled()) {
+            Log.d(TAG, "Image was recyled by GC. Task is cancelled. " + memoryCacheKey);
+        } else if (isViewWasReused()) {
+            Log.d(TAG, "Image is reused for another image. Task is cancelled. " + memoryCacheKey);
+        } else {
+            Log.d(TAG, "Display image in ImageAware (loaded from " + memoryCacheKey);
+            imageView.setImageBitmap(bitmap);
+            handle.cacheKeysForImageAwares.remove(imageView.getId());
+        }
+    }
+
+    private boolean isViewWasReused() {
+        String currentCacheKey = handle.cacheKeysForImageAwares.get(imageView.getId());
+        return !memoryCacheKey.equals(currentCacheKey);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java
new file mode 100644
index 0000000..f9ec8b2
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderConfig.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+
+public class ImageLoaderConfig {
+
+    private final String TAG = "ImageLoaderConfig";
+    private static final String URI_AND_SIZE_SEPARATOR = "_";
+    private static final String WIDTH_AND_HEIGHT_SEPARATOR = "x";
+    final Resources resources;
+
+    public static final int DEFAULT_THREAD_POOL_SIZE = 4;
+    public static final int DEFAULT_THREAD_PRIORITY = Thread.NORM_PRIORITY - 2;
+    public Context context;
+
+    public Executor taskExecutor = null;
+    public boolean customExecutor = false;
+
+    public int threadPoolSize = DEFAULT_THREAD_POOL_SIZE;
+    public int threadPriority = DEFAULT_THREAD_PRIORITY;
+
+    private LinkedHashMap<String, Bitmap> imageCacheMap;
+    private int icmMaxSize;
+    private int icmSize;
+    public ImageLoaderOptions defaultOptions = null;
+
+    public ImageLoaderConfig(Context context) {
+        this.context = context.getApplicationContext();
+        resources = context.getResources();
+        initEmptyFieldsWithDefaultValues();
+    }
+
+    public void cacheMapSizePercentage(int availableMemoryPercent) {
+        if (availableMemoryPercent <= 0 || availableMemoryPercent >= 100) {
+            throw new IllegalArgumentException("availableMemoryPercent must be in range (0 < % < 100)");
+        }
+
+        long availableMemory = Runtime.getRuntime().maxMemory();
+        icmMaxSize = (int) (availableMemory * (availableMemoryPercent / 100f));
+    }
+
+    private void initEmptyFieldsWithDefaultValues() {
+        if (taskExecutor == null) {
+            taskExecutor = createExecutor(threadPoolSize, threadPriority);
+        } else {
+            customExecutor = true;
+        }
+        if (imageCacheMap == null) {
+            icmSize = 0;
+            imageCacheMap = new LinkedHashMap<String, Bitmap>(0, 0.75f, true);
+        }
+        if (defaultOptions == null) {
+            defaultOptions = new ImageLoaderOptions();
+        }
+    }
+
+    public final Bitmap get(String key) {
+        if (key == null) {
+            throw new NullPointerException("key == null");
+        }
+
+        synchronized (this) {
+            return imageCacheMap.get(key);
+        }
+    }
+
+    public final boolean put(String key, Bitmap value) {
+        if (key == null || value == null) {
+            throw new NullPointerException("key == null || value == null");
+        }
+
+        synchronized (this) {
+            icmSize += sizeOf(value);
+            Bitmap previous = imageCacheMap.put(key, value);
+            if (previous != null) {
+                icmSize -= sizeOf(previous);
+            }
+        }
+
+        trimToSize(icmMaxSize);
+        return true;
+    }
+
+    private void trimToSize(int maxSize) {
+        while (true) {
+            String key;
+            Bitmap value;
+            synchronized (this) {
+                if (icmSize < 0 || (imageCacheMap.isEmpty() && icmSize != 0)) {
+                    throw new IllegalStateException(getClass().getName() + ".sizeOf() is inconsistent!");
+                }
+
+                if (icmSize <= maxSize || imageCacheMap.isEmpty()) {
+                    break;
+                }
+
+                Map.Entry<String, Bitmap> toEvict = imageCacheMap.entrySet().iterator().next();
+                if (toEvict == null) {
+                    break;
+                }
+                key = toEvict.getKey();
+                value = toEvict.getValue();
+                imageCacheMap.remove(key);
+                icmSize -= sizeOf(value);
+            }
+        }
+    }
+
+    public final Bitmap remove(String key) {
+        if (key == null) {
+            throw new NullPointerException("key == null");
+        }
+
+        synchronized (this) {
+            Bitmap previous = imageCacheMap.remove(key);
+            if (previous != null) {
+                icmSize -= sizeOf(previous);
+            }
+            return previous;
+        }
+    }
+
+    private int sizeOf(Bitmap value) {
+        return value.getRowBytes() * value.getHeight();
+    }
+
+
+    public int defineHeightForImage(ImageViewImpl imageView) {
+        int height = imageView.getHeight();
+        if (height <= 0)
+            height = resources.getDisplayMetrics().heightPixels;
+        return height;
+    }
+
+    public int defineWidthForImage(ImageViewImpl imageView) {
+        int width = imageView.getWidth();
+        if (width <= 0)
+            width = resources.getDisplayMetrics().widthPixels;
+        return width;
+    }
+
+    public static String generateKey(String imageUri, int w, int h) {
+        return new StringBuilder(imageUri).append(URI_AND_SIZE_SEPARATOR).append(w)
+                .append(WIDTH_AND_HEIGHT_SEPARATOR).append(h).toString();
+    }
+
+    public static Executor createExecutor(int threadPoolSize, int threadPriority) {
+        BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<Runnable>();
+        return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS,
+                taskQueue, new ThreadFactoryImpl(threadPriority));
+    }
+
+    public static Handler defineHandler(ImageLoaderOptions options) {
+        Handler handler = options.getHandler();
+        if (handler == null && Looper.myLooper() == Looper.getMainLooper()) {
+            handler = new Handler();
+        }
+        return handler;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java
new file mode 100644
index 0000000..a7ed640
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderHandle.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.locks.ReentrantLock;
+
+class ImageLoaderHandle {
+
+    final ImageLoaderConfig configuration;
+
+    public Executor taskExecutor;
+    public Executor taskDistributor;
+
+    public final Map<Integer, String> cacheKeysForImageAwares = Collections
+            .synchronizedMap(new HashMap<Integer, String>());
+    private final Map<String, ReentrantLock> uriLocks = new WeakHashMap<String, ReentrantLock>();
+    private final Object pauseLock = new Object();
+
+    ImageLoaderHandle(ImageLoaderConfig configuration) {
+        this.configuration = configuration;
+
+        taskExecutor = configuration.taskExecutor;
+        taskDistributor = createTaskDistributor();
+    }
+
+    /** Submits task to execution pool */
+    void submit(final ImageLoaderTask task) {
+        taskDistributor.execute(new Runnable() {
+            @Override
+            public void run() {
+                if (!configuration.customExecutor && ((ExecutorService) taskExecutor).isShutdown()) {
+                    taskExecutor = configuration.createExecutor(configuration.threadPoolSize,
+                            configuration.threadPriority);
+                }
+                taskExecutor.execute(task);
+            }
+        });
+    }
+
+    ReentrantLock getLockForUri(String uri) {
+        ReentrantLock lock = uriLocks.get(uri);
+        if (lock == null) {
+            lock = new ReentrantLock();
+            uriLocks.put(uri, lock);
+        }
+        return lock;
+    }
+
+    public static Executor createTaskDistributor() {
+        return Executors.newCachedThreadPool(new ThreadFactoryImpl(Thread.NORM_PRIORITY));
+    }
+
+    void prepareDisplayTaskFor(ImageViewImpl imageView, String memoryCacheKey) {
+        cacheKeysForImageAwares.put(imageView.getId(), memoryCacheKey);
+    }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java
new file mode 100644
index 0000000..6514a68
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInfo.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Information for load'n'display image task
+ */
+final class ImageLoaderInfo {
+
+    final String uri;
+    final String memoryCacheKey;
+    final ImageViewImpl imageView;
+    final int targetHeight;
+    final int targetWidth;
+    final ImageLoaderOptions options;
+    final ReentrantLock loadFromUriLock;
+
+    public ImageLoaderInfo(String uri, ImageViewImpl imageView, int height, int width, String memoryCacheKey,
+                            ImageLoaderOptions options, ReentrantLock loadFromUriLock) {
+        this.uri = uri;
+        this.imageView = imageView;
+        this.targetHeight = height;
+        this.targetWidth = width;
+        this.options = options;
+        this.loadFromUriLock = loadFromUriLock;
+        this.memoryCacheKey = memoryCacheKey;
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java
new file mode 100644
index 0000000..5839d82
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderInstance.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+import android.util.Log;
+
+public class ImageLoaderInstance {
+
+    private ImageLoaderHandle handle;
+    private ImageLoaderConfig configuration;
+    private volatile static ImageLoaderInstance instance;
+    private static final String TAG = "ImageLoaderInstance";
+
+    /** Returns singleton class instance */
+    public static ImageLoaderInstance getInstance() {
+        if (instance == null) {
+            synchronized (ImageLoaderInstance.class) {
+                if (instance == null) {
+                    instance = new ImageLoaderInstance();
+                }
+            }
+        }
+        return instance;
+    }
+
+    protected ImageLoaderInstance() {
+    }
+
+    public synchronized void init(ImageLoaderConfig configuration) {
+        if (this.configuration == null) {
+            handle = new ImageLoaderHandle(configuration);
+            this.configuration = configuration;
+        }
+    }
+
+    public void displayImage(String uri, ImageViewImpl imageView, ImageLoaderOptions options){
+        if (imageView == null) {
+            throw new IllegalArgumentException("Null iamgeView were passed.");
+        }
+        if (TextUtils.isEmpty(uri)) {
+            handle.cacheKeysForImageAwares.remove(imageView.getId());
+            imageView.setImageDrawable(options.getImageForEmptyUri(configuration.resources));
+            return;
+        }
+
+        int imageHeight = configuration.defineHeightForImage(imageView);
+        int imageWidth = configuration.defineWidthForImage(imageView);
+        String memoryCacheKey = configuration.generateKey(uri, imageHeight, imageWidth);
+        handle.prepareDisplayTaskFor(imageView, memoryCacheKey);
+
+        Bitmap bmp = configuration.get(memoryCacheKey);
+        if (bmp != null && !bmp.isRecycled()) {
+            Log.d(TAG, "Load image from memory cache " + memoryCacheKey);
+            imageView.setImageBitmap(bmp);
+        } else {
+            imageView.setImageDrawable(options.getImageOnLoading(configuration.resources));
+            ImageLoaderInfo imageLoadingInfo = new ImageLoaderInfo(uri, imageView, imageHeight, imageWidth,
+                    memoryCacheKey, options, handle.getLockForUri(uri));
+            ImageLoaderTask displayTask = new ImageLoaderTask(handle, imageLoadingInfo,
+                    configuration.defineHandler(options));
+            handle.submit(displayTask);
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java
new file mode 100644
index 0000000..2e6261f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderOptions.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import org.codeaurora.gallery.R;
+
+public class ImageLoaderOptions {
+
+    private int imageResOnLoading = R.color.picker_imageloading;
+    private int imageResForEmptyUri = 0;
+    private Drawable imageOnLoading = null;
+    private Drawable imageForEmptyUri = null;
+    private Handler handler = null;
+
+    public Drawable getImageOnLoading(Resources res) {
+        return imageResOnLoading != 0 ? res.getDrawable(imageResOnLoading) : imageOnLoading;
+    }
+
+    public Drawable getImageForEmptyUri(Resources res) {
+        return imageResForEmptyUri != 0 ? res.getDrawable(imageResForEmptyUri) : imageForEmptyUri;
+    }
+
+    public Handler getHandler() {
+        return handler;
+    }
+
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java
new file mode 100644
index 0000000..454715f
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderStub.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.Context;
+import android.net.Uri;
+import android.widget.ImageView;
+
+
+public class ImageLoaderStub {
+    private ImageLoaderConfig configuration;
+
+    public ImageLoaderStub(Context context) {
+        configuration = new ImageLoaderConfig(context);
+        configuration.cacheMapSizePercentage(30);
+        ImageLoaderInstance.getInstance().init(configuration);
+    }
+
+    public void displayImage(Uri uri, ImageView imageView) {
+        ImageLoaderOptions displayImageOptions = new ImageLoaderOptions();
+
+        ImageViewImpl imageViewImpl = new ImageViewImpl(imageView);
+        ImageLoaderInstance.getInstance().displayImage(uri.toString(), imageViewImpl, displayImageOptions);
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java
new file mode 100644
index 0000000..7716a87
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageLoaderTask.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.content.ContentResolver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
+import android.net.Uri;
+import android.os.Handler;
+import android.util.Log;
+
+import java.io.Closeable;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.locks.ReentrantLock;
+
+final class ImageLoaderTask implements Runnable {
+
+    private final String TAG = "ImageLoaderTask";
+    private final ImageLoaderHandle handle;
+    private final ImageLoaderInfo imageLoadingInfo;
+    private final Handler handler;
+
+    final String uri;
+    private final String memoryCacheKey;
+    final ImageViewImpl imageView;
+    private int imageHeight, imageWidth;
+
+    public ImageLoaderTask(ImageLoaderHandle handle, ImageLoaderInfo imageLoadingInfo, Handler handler) {
+        this.handle = handle;
+        this.imageLoadingInfo = imageLoadingInfo;
+        this.handler = handler;
+
+        uri = imageLoadingInfo.uri;
+        memoryCacheKey = imageLoadingInfo.memoryCacheKey;
+        imageView = imageLoadingInfo.imageView;
+        imageHeight = imageLoadingInfo.targetHeight;
+        imageWidth = imageLoadingInfo.targetWidth;
+    }
+
+    @Override
+    public void run() {
+        if (isTaskAvailable()) return;
+
+        ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock;
+        Log.d(TAG, "Start display image task " + memoryCacheKey);
+        loadFromUriLock.lock();
+        Bitmap bmp = null;
+        try {
+            checkTaskNotActual();
+            checkTaskInterrupted();
+            bmp = handle.configuration.get(memoryCacheKey);
+            if (bmp == null || bmp.isRecycled()) {
+                bmp = parseImage(uri);
+                if (bmp == null) return;
+
+                checkTaskNotActual();
+                checkTaskInterrupted();
+                if (bmp != null) {
+                    Log.d(TAG, "Cache image in memory " + memoryCacheKey);
+                    handle.configuration.put(memoryCacheKey, bmp);
+                }
+            } else {
+                Log.d(TAG, "Get cached bitmap from memory after waiting. " + memoryCacheKey);
+            }
+            checkTaskNotActual();
+            checkTaskInterrupted();
+        } catch (TaskInvalidException e) {
+            return;
+        } catch (IOException e) {
+            Log.e(TAG, e.toString());
+        } catch (OutOfMemoryError e) {
+            Log.e(TAG, e.toString());
+        } catch (Throwable e) {
+            Log.e(TAG, e.toString());
+        } finally {
+            loadFromUriLock.unlock();
+        }
+        ImageDisplayTask displayBitmapTask = new ImageDisplayTask(bmp, imageLoadingInfo, handle);
+        runTask(displayBitmapTask, handler, handle);
+    }
+
+
+    private Bitmap parseImage(String imageUri) throws IOException {
+        ViewScaleType viewScaleType = imageView.getScaleType();
+        Bitmap parsedBitmap;
+        BitmapFactory.Options opt;
+
+        InputStream imageStream = getImageStream(imageUri);
+        try {
+            opt = getImageOpt(imageStream);
+            imageStream = resetStream(imageStream, imageUri);
+            int scale = computeImageSampleSize(opt, imageHeight, imageWidth, viewScaleType);
+            BitmapFactory.Options decodingOptions = new BitmapFactory.Options();
+            decodingOptions.inSampleSize = scale;
+            parsedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
+        } finally {
+            closeSilently(imageStream);
+        }
+
+        if (parsedBitmap == null) {
+            Log.e(TAG, "Image can't be parsed: " + memoryCacheKey);
+        } else {
+            parsedBitmap = checkScale(parsedBitmap);
+        }
+        return parsedBitmap;
+    }
+
+    public static void closeSilently(Closeable closeable) {
+        try {
+            closeable.close();
+        } catch (Exception e) {
+            // Just catched here.
+        }
+    }
+
+    protected InputStream getImageStream(String imageUri) throws FileNotFoundException {
+        ContentResolver res = handle.configuration.context.getContentResolver();
+        Uri uri = Uri.parse(imageUri);
+        return res.openInputStream(uri);
+    }
+
+    protected BitmapFactory.Options getImageOpt(InputStream imageStream)
+            throws IOException {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inJustDecodeBounds = true;
+        BitmapFactory.decodeStream(imageStream, null, options);
+
+        return options;
+    }
+
+    protected InputStream resetStream(InputStream imageStream, String imageUri) throws IOException {
+        try {
+            imageStream.reset();
+        } catch (IOException e) {
+            closeSilently(imageStream);
+            imageStream = getImageStream(imageUri);
+        }
+        return imageStream;
+    }
+
+    public static int computeImageSampleSize(BitmapFactory.Options opt, int h, int w,
+                                             ViewScaleType viewScaleType) {
+        final int width = opt.outWidth/2;
+        final int height = opt.outHeight/2;
+        final int maxWidth = 2048;
+        final int maxHeight = 2048;
+
+        int scale = 1;
+        switch (viewScaleType) {
+            case FIT_INSIDE:
+                while ((width / scale) > w || (height / scale) > h) {
+                    scale *= 2;
+                }
+                break;
+            case CROP:
+                while ((width / scale) > w && (height / scale) > h) {
+                        scale *= 2;
+                }
+                break;
+        }
+        while ((opt.outWidth / scale) > maxWidth || (opt.outHeight / scale) > maxHeight) {
+            scale *= 2;
+        }
+        return scale;
+    }
+
+    protected Bitmap checkScale(Bitmap subsampledBitmap) {
+        Matrix m = new Matrix();
+
+        Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, subsampledBitmap.getWidth(),
+                subsampledBitmap.getHeight(), m, true);
+        if (finalBitmap != subsampledBitmap) {
+            subsampledBitmap.recycle();
+        }
+        return finalBitmap;
+    }
+
+    private boolean isTaskAvailable() {
+        if (isRecyled() || isCached())
+            return true;
+        return false;
+    }
+
+    private void checkTaskNotActual() throws TaskInvalidException {
+        if (isRecyled()) {
+            throw new TaskInvalidException();
+        }
+        if (isCached()) {
+            throw new TaskInvalidException();
+        }
+    }
+
+    private boolean isRecyled() {
+        if (imageView.isRecyled()) {
+            Log.d(TAG,"ImageAware was collected by GC. Task is cancelled: " + memoryCacheKey);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isCached() {
+        String cntCacheKey = handle.cacheKeysForImageAwares.get(imageView.getId());
+        if (!memoryCacheKey.equals(cntCacheKey)) {
+            Log.d(TAG, "Imageview is cached for another image: " + memoryCacheKey);
+            return true;
+        }
+        return false;
+    }
+
+    private void checkTaskInterrupted() throws TaskInvalidException {
+        if (Thread.interrupted()) {
+            throw new TaskInvalidException();
+        }
+    }
+
+    static void runTask(Runnable r, Handler handler, ImageLoaderHandle handle) {
+        if (handler == null) {
+            handle.taskDistributor.execute(r);
+        } else {
+            handler.post(r);
+        }
+    }
+
+    class TaskInvalidException extends Exception {
+    }
+}
+
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java
new file mode 100644
index 0000000..3f1e2b1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ImageViewImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Looper;
+import android.util.Log;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Field;
+
+
+public class ImageViewImpl{
+
+    private final static String TAG = "ImageViewImpl";
+    protected Reference<View> viewRef;
+
+
+    public ImageViewImpl(ImageView imageView) {
+        if (imageView == null) throw new IllegalArgumentException("view must not be null");
+
+        this.viewRef = new WeakReference<View>(imageView);
+    }
+
+    public int getWidth() {
+        int width = 0;
+        View view = viewRef.get();
+        if (view != null) {
+            final ViewGroup.LayoutParams params = view.getLayoutParams();
+
+            if (width <= 0 && params != null) width = params.width; // Get layout width parameter
+        }
+        if (width <= 0) {
+            ImageView imageView = (ImageView) viewRef.get();
+            if (imageView != null) {
+                width = getImageViewFieldValue(imageView, "mMaxWidth"); // Check maxWidth parameter
+            }
+        }
+        return width;
+    }
+
+    public int getHeight() {
+        int height = 0;
+        View view = viewRef.get();
+        if (view != null) {
+            final ViewGroup.LayoutParams params = view.getLayoutParams();
+            if (height <= 0 && params != null) height = params.height; // Get layout height parameter
+            return height;
+        }
+        if (height <= 0) {
+            ImageView imageView = (ImageView) viewRef.get();
+            if (imageView != null) {
+                height = getImageViewFieldValue(imageView, "mMaxHeight"); // Check maxHeight parameter
+            }
+        }
+        return height;
+    }
+
+    public boolean setImageDrawable(Drawable drawable) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            View view = viewRef.get();
+            if (view != null) {
+                ((ImageView) view).setImageDrawable(drawable);
+                if (drawable instanceof AnimationDrawable) {
+                    ((AnimationDrawable)drawable).start();
+                }
+                return true;
+            }
+        } else {
+            Log.w(TAG, "Can't set a bitmap into view. You should call ImageLoader on UI thread for it.");
+        }
+        return false;
+    }
+
+    public int getId() {
+        View view = viewRef.get();
+        return view == null ? super.hashCode() : view.hashCode();
+    }
+
+    private static int getImageViewFieldValue(Object object, String fieldName) {
+        int value = 0;
+        try {
+            Field field = ImageView.class.getDeclaredField(fieldName);
+            field.setAccessible(true);
+            int fieldValue = (Integer) field.get(object);
+            if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE) {
+                value = fieldValue;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+        }
+        return value;
+    }
+
+    public ViewScaleType getScaleType() {
+        ImageView imageView = (ImageView) viewRef.get();
+        if (imageView != null) {
+            return ViewScaleType.fromImageView(imageView);
+        }
+        return ViewScaleType.CROP;
+    }
+
+    public boolean setImageBitmap(Bitmap bitmap) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            View view = viewRef.get();
+            if (view != null) {
+                ((ImageView) view).setImageBitmap(bitmap);
+                return true;
+            }
+        } else {
+            Log.w(TAG, "Can't set a bitmap into view. You should call ImageLoader on UI thread for it.");
+        }
+        return false;
+    }
+
+    public boolean isRecyled() {
+        return viewRef.get() == null;
+    }
+}
+
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java
new file mode 100644
index 0000000..fe3f582
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ThreadFactoryImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import java.util.concurrent.ThreadFactory;
+
+class ThreadFactoryImpl implements ThreadFactory {
+
+    private final ThreadGroup group;
+    private final int threadPriority;
+
+    ThreadFactoryImpl(int threadPriority) {
+        this.threadPriority = threadPriority;
+        group = Thread.currentThread().getThreadGroup();
+    }
+
+    @Override
+    public Thread newThread(Runnable r) {
+        Thread t = new Thread(group, r);
+        if (t.isDaemon()) t.setDaemon(false);
+        t.setPriority(threadPriority);
+        return t;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java
new file mode 100644
index 0000000..2984693
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/mediapicker/imageloader/ViewScaleType.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.mediapicker.imageloader;
+
+import android.widget.ImageView;
+
+
+public enum ViewScaleType {
+    FIT_INSIDE,
+    CROP;
+
+    public static ViewScaleType fromImageView(ImageView imageView) {
+        switch (imageView.getScaleType()) {
+            case FIT_CENTER:
+            case FIT_XY:
+            case FIT_START:
+            case FIT_END:
+            case CENTER_INSIDE:
+                return FIT_INSIDE;
+            case MATRIX:
+            case CENTER:
+            case CENTER_CROP:
+            default:
+                return CROP;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
index a487a5d..c3120d7 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java
@@ -18,9 +18,10 @@
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.renderscript.Allocation;
 import android.renderscript.RenderScript;
-import android.util.Log;
+
 import com.android.gallery3d.filtershow.cache.BitmapCache;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 
@@ -57,6 +58,7 @@
     }
 
     public synchronized void useBitmap(Bitmap bitmap) {
+        mBitmap.eraseColor(Color.TRANSPARENT);
         Canvas canvas = new Canvas(mBitmap);
         canvas.drawBitmap(bitmap, 0, 0, null);
     }
diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
index 0b84f52..b56fdba 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java
@@ -129,6 +129,7 @@
         ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation);
         if (filter == null){
             Log.e(LOGTAG,"No ImageFilter for "+representation.getSerializationName());
+            return bitmap;
         }
         filter.useRepresentation(representation);
         filter.setEnvironment(this);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
index 9166ee3..f5a5689 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java
@@ -16,6 +16,13 @@
 
 package com.android.gallery3d.filtershow.pipeline;
 
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Vector;
+
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.renderscript.Allocation;
@@ -23,17 +30,20 @@
 import android.util.JsonWriter;
 import android.util.Log;
 
-import com.android.gallery3d.R;
-import com.android.gallery3d.filtershow.cache.BitmapCache;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.filters.BaseFiltersManager;
 import com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamBasicRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterFxRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterPresetRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTruePortraitFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -42,13 +52,6 @@
 import com.android.gallery3d.filtershow.state.State;
 import com.android.gallery3d.filtershow.state.StateAdapter;
 
-import java.io.IOException;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Vector;
-
 public class ImagePreset {
 
     private static final String LOGTAG = "ImagePreset";
@@ -67,9 +70,11 @@
     }
 
     public ImagePreset(ImagePreset source) {
-        for (int i = 0; i < source.mFilters.size(); i++) {
-            FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i);
-            mFilters.add(sourceRepresentation.copy());
+        if (source != null && source.mFilters != null) {
+            for (int i = 0; i < source.mFilters.size(); i++) {
+                FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i);
+                mFilters.add(sourceRepresentation.copy());
+            }
         }
     }
 
@@ -151,6 +156,7 @@
     }
 
     public void updateOrAddFilterRepresentation(FilterRepresentation rep) {
+        if (rep == null) return;
         int pos = getPositionForRepresentation(rep);
         if (pos != -1) {
             mFilters.elementAt(pos).useParametersFrom(rep);
@@ -163,6 +169,10 @@
         mDoApplyGeometry = value;
     }
 
+    public boolean getDoApplyGeometry() {
+        return mDoApplyGeometry;
+    }
+
     public void setDoApplyFilters(boolean value) {
         mDoApplyFilters = value;
     }
@@ -237,7 +247,7 @@
                 FilterRepresentation a = preset.mFilters.elementAt(i);
                 FilterRepresentation b = mFilters.elementAt(i);
 
-                if (!a.same(b)) {
+                if (!a.equals(b)) {
                     return false;
                 }
             }
@@ -325,11 +335,21 @@
     }
 
     public void removeFilter(FilterRepresentation filterRepresentation) {
-        if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) {
+        if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER
+                || filterRepresentation.getFilterType() == FilterRepresentation.TYPE_DUALCAM
+                || filterRepresentation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT) {
             for (int i = 0; i < mFilters.size(); i++) {
-                if (mFilters.elementAt(i).getFilterType()
-                == filterRepresentation.getFilterType()) {
+                FilterRepresentation filter = mFilters.elementAt(i);
+                if (filter.getFilterType() == filterRepresentation.getFilterType()) {
                     mFilters.remove(i);
+
+                    // reset fusion underlay image.
+                    if(filter instanceof FilterDualCamFusionRepresentation ||
+                            filter instanceof FilterTruePortraitFusionRepresentation) {
+                        MasterImage.getImage().setFusionUnderlay(null);
+                        MasterImage.getImage().setScaleFactor(1);
+                        MasterImage.getImage().resetTranslation();
+                    }
                     break;
                 }
             }
@@ -348,7 +368,7 @@
         if (representation instanceof FilterUserPresetRepresentation) {
             ImagePreset preset = ((FilterUserPresetRepresentation) representation).getImagePreset();
             if (preset.nbFilters() == 1
-                && preset.contains(FilterRepresentation.TYPE_FX)) {
+                    && preset.contains(FilterRepresentation.TYPE_FX)) {
                 FilterRepresentation rep = preset.getFilterRepresentationForType(
                         FilterRepresentation.TYPE_FX);
                 addFilter(rep);
@@ -381,11 +401,22 @@
             if (!isNoneBorderFilter(representation)) {
                 mFilters.add(representation);
             }
+        } else if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+            removeFilter(representation);
+            if (!isNoneDualCamFilter(representation)) {
+                mFilters.add(representation);
+            }
+        } else if (representation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT) {
+            removeFilter(representation);
+            if (!isNoneTruePortraitFilter(representation)) {
+                mFilters.add(representation);
+            }
         } else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) {
             boolean replaced = false;
             for (int i = 0; i < mFilters.size(); i++) {
                 FilterRepresentation current = mFilters.elementAt(i);
-                if (current.getFilterType() == FilterRepresentation.TYPE_FX) {
+                if (current.getFilterType() == FilterRepresentation.TYPE_FX
+                        || (current.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER)) {
                     mFilters.remove(i);
                     replaced = true;
                     if (!isNoneFxFilter(representation)) {
@@ -395,25 +426,87 @@
                 }
             }
             if (!replaced && !isNoneFxFilter(representation)) {
-                mFilters.add(0, representation);
+                mFilters.add(representation);
+            }
+        } else if (representation.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER) {
+            boolean replaced = false;
+            for (int i = 0; i < mFilters.size(); i++) {
+                FilterRepresentation current = mFilters.elementAt(i);
+                if ((current.getFilterType() == FilterRepresentation.TYPE_PRESETFILTER)
+                        || (current.getFilterType() == FilterRepresentation.TYPE_FX)) {
+                    mFilters.remove(i);
+                    replaced = true;
+                    if (!isNonePresetFilter(representation)) {
+                        mFilters.add(i, representation);
+                    }
+                    break;
+                }
+            }
+            if (!replaced && !isNonePresetFilter(representation)) {
+                mFilters.add(representation);
+            }
+        } else if (representation.getFilterType() == FilterRepresentation.TYPE_WATERMARK) {
+            boolean replaced = false;
+            for (int i = 0; i < mFilters.size(); i++) {
+                FilterRepresentation current = mFilters.elementAt(i);
+                if (current.getFilterType() == FilterRepresentation.TYPE_WATERMARK) {
+                    mFilters.remove(i);
+                    replaced = true;
+                    mFilters.add(i, representation);
+                    break;
+                }
+            }
+            if (!replaced) {
+                mFilters.add(representation);
             }
         } else {
             mFilters.add(representation);
         }
-        // Enforces Filter type ordering for borders
+
+        // Enforces Filter type ordering for borders and dual cam
         FilterRepresentation border = null;
+        FilterRepresentation dualcam = null;
+        FilterRepresentation trueportrait = null;
         for (int i = 0; i < mFilters.size();) {
             FilterRepresentation rep = mFilters.elementAt(i);
             if (rep.getFilterType() == FilterRepresentation.TYPE_BORDER) {
                 border = rep;
                 mFilters.remove(i);
                 continue;
+            } else if (rep.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+                dualcam = rep;
+                mFilters.remove(i);
+                continue;
+            } else if (rep.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT) {
+                trueportrait = rep;
+                mFilters.remove(i);
+                continue;
             }
             i++;
         }
         if (border != null) {
             mFilters.add(border);
         }
+        if (dualcam != null) {
+            int i = 0;
+            for (; i < mFilters.size(); i++) {
+                FilterRepresentation rep = mFilters.elementAt(i);
+                if (rep.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
+                    break;
+                }
+            }
+            mFilters.add(i, dualcam);
+        }
+        if (trueportrait != null) {
+            int i = 0;
+            for (; i < mFilters.size(); i++) {
+                FilterRepresentation rep = mFilters.elementAt(i);
+                if (rep.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) {
+                    break;
+                }
+            }
+            mFilters.add(i, trueportrait);
+        }
     }
 
     private boolean isNoneBorderFilter(FilterRepresentation representation) {
@@ -426,6 +519,21 @@
                 ((FilterFxRepresentation) representation).getNameResource() == R.string.none;
     }
 
+    private boolean isNoneDualCamFilter(FilterRepresentation representation) {
+        return representation instanceof FilterDualCamBasicRepresentation &&
+                representation.getTextId() == R.string.none;
+    }
+
+    private boolean isNoneTruePortraitFilter(FilterRepresentation representation) {
+        return representation.getTextId() == R.string.none &&
+                representation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT;
+    }
+
+    private boolean isNonePresetFilter(FilterRepresentation representation) {
+        return representation instanceof FilterPresetRepresentation &&
+                ((FilterPresetRepresentation) representation).getTextId() == R.string.none;
+    }
+
     public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) {
         for (int i = 0; i < mFilters.size(); i++) {
             FilterRepresentation representation = mFilters.elementAt(i);
@@ -438,6 +546,8 @@
 
     public Bitmap apply(Bitmap original, FilterEnvironment environment) {
         Bitmap bitmap = original;
+        bitmap = applyDualCamera(bitmap, environment);
+        bitmap = applyTruePortrait(bitmap, environment);
         bitmap = applyFilters(bitmap, -1, -1, environment);
         return applyBorder(bitmap, environment);
     }
@@ -481,6 +591,44 @@
         return bitmap;
     }
 
+    public Bitmap applyDualCamera(Bitmap bitmap, FilterEnvironment environment) {
+        // Apply dual camera filters
+        // Returns a new bitmap.
+        for (FilterRepresentation representation:mFilters) {
+            if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+                Bitmap tmp = bitmap;
+                bitmap = environment.applyRepresentation(representation, bitmap);
+                if (tmp != bitmap) {
+                    environment.cache(tmp);
+                }
+                if (environment.needsStop()) {
+                    return bitmap;
+                }
+            }
+        }
+
+        return bitmap;
+    }
+
+    public Bitmap applyTruePortrait(Bitmap bitmap, FilterEnvironment environment) {
+        // Apply trueportrait filters
+        // Returns a new bitmap.
+        for (FilterRepresentation representation:mFilters) {
+            if (representation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT) {
+                Bitmap tmp = bitmap;
+                bitmap = environment.applyRepresentation(representation, bitmap);
+                if (tmp != bitmap) {
+                    environment.cache(tmp);
+                }
+                if (environment.needsStop()) {
+                    return bitmap;
+                }
+            }
+        }
+
+        return bitmap;
+    }
+
     public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) {
         // get the border from the list of filters.
         FilterRepresentation border = getFilterRepresentationForType(
@@ -517,6 +665,14 @@
                     // TODO: might be worth getting rid of applyBorder.
                     continue;
                 }
+                if (representation.getFilterType() == FilterRepresentation.TYPE_DUALCAM) {
+                    // skip the dual cam as it's already applied.
+                    continue;
+                }
+                if (representation.getFilterType() == FilterRepresentation.TYPE_TRUEPORTRAIT) {
+                    // skip the true portrait as it's already applied.
+                    continue;
+                }
                 Bitmap tmp = bitmap;
                 bitmap = environment.applyRepresentation(representation, bitmap);
                 if (tmp != bitmap) {
@@ -645,6 +801,9 @@
                     continue;
                 }
                 String sname = filter.getSerializationName();
+                if (sname == null) {
+                    continue;
+                }
                 if (DEBUG) {
                     Log.v(LOGTAG, "Serialization: " + sname);
                     if (sname == null) {
@@ -657,7 +816,7 @@
             writer.endObject();
 
         } catch (IOException e) {
-           Log.e(LOGTAG,"Error encoding JASON",e);
+            Log.e(LOGTAG,"Error encoding JASON",e);
         }
     }
 
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java b/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java
index 801aee4..dd0ef23 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java
@@ -20,7 +20,11 @@
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.net.Uri;
+
+import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.app.Log;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.tools.SaveImage;
 
@@ -39,6 +43,7 @@
         float sizeFactor;
         Bitmap previewImage;
         boolean exit;
+        long requsetId;
     }
 
     static class UpdateBitmap implements Update {
@@ -58,6 +63,7 @@
     static class URIResult implements Result {
         Uri uri;
         boolean exit;
+        long requestId;
     }
 
     public ImageSavingTask(ProcessingService service) {
@@ -67,7 +73,7 @@
     public void saveImage(Uri sourceUri, Uri selectedUri,
                           File destinationFile, ImagePreset preset,
                           Bitmap previewImage, boolean flatten,
-                          int quality, float sizeFactor, boolean exit) {
+                          int quality, float sizeFactor, boolean exit, long requestId) {
         SaveRequest request = new SaveRequest();
         request.sourceUri = sourceUri;
         request.selectedUri = selectedUri;
@@ -78,6 +84,7 @@
         request.sizeFactor = sizeFactor;
         request.previewImage = previewImage;
         request.exit = exit;
+        request.requsetId = requestId;
         postRequest(request);
     }
 
@@ -116,25 +123,27 @@
                 });
         Uri uri = saveImage.processAndSaveImage(preset, flatten,
                 request.quality, request.sizeFactor, request.exit);
+        if (uri != null) {
+            FilterRepresentation rep = preset.getFilterRepresentation(0);
+            if (rep != null) {
+                Log.d(GalleryActivity.QSST, "edited image saved successfully " + rep.getName());
+            }
+        }
         URIResult result = new URIResult();
         result.uri = uri;
         result.exit = request.exit;
+        result.requestId = request.requsetId;
         return result;
     }
 
     @Override
     public void onResult(Result message) {
         URIResult result = (URIResult) message;
-        mProcessingService.completeSaveImage(result.uri, result.exit);
+        mProcessingService.completeSaveImage(result.uri, result.requestId, result.exit, true);
     }
 
     @Override
     public void onUpdate(Update message) {
-        if (message instanceof UpdatePreviewSaved){
-            Uri uri = ((UpdatePreviewSaved) message).uri;
-            boolean exit = ((UpdatePreviewSaved) message).exit;
-            mProcessingService.completePreviewSaveImage(uri, exit);
-        }
         if (message instanceof UpdateBitmap) {
             Bitmap bitmap = ((UpdateBitmap) message).bitmap;
             mProcessingService.updateNotificationWithBitmap(bitmap);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
old mode 100644
new mode 100755
index e5736d4..cd3dfe7
--- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java
@@ -17,6 +17,7 @@
 package com.android.gallery3d.filtershow.pipeline;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.Service;
 import android.content.Context;
@@ -26,9 +27,12 @@
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.util.Log;
-import com.android.gallery3d.R;
+
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.filters.ImageFilter;
@@ -53,6 +57,11 @@
     private static final String FLATTEN = "flatten";
     private static final String SIZE_FACTOR = "sizeFactor";
     private static final String EXIT = "exit";
+    private static final String REQUEST_ID = "request_id";
+
+    public static final String SAVE_IMAGE_COMPLETE_ACTION = "save_image_complete_action";
+    public static final String KEY_URL = "key_url";
+    public static final String KEY_REQUEST_ID = "request_id";
 
     private ProcessingTaskController mProcessingTaskController;
     private ImageSavingTask mImageSavingTask;
@@ -62,14 +71,7 @@
     private RenderingRequestTask mRenderingRequestTask;
 
     private final IBinder mBinder = new LocalBinder();
-    private FilterShowActivity mFiltershowActivity;
 
-    private boolean mSaving = false;
-    private boolean mNeedsAlive = false;
-
-    public void setFiltershowActivity(FilterShowActivity filtershowActivity) {
-        mFiltershowActivity = filtershowActivity;
-    }
 
     public void setOriginalBitmap(Bitmap originalBitmap) {
         if (mUpdatePreviewTask == null) {
@@ -142,7 +144,7 @@
 
     public static Intent getSaveIntent(Context context, ImagePreset preset, File destination,
             Uri selectedImageUri, Uri sourceImageUri, boolean doFlatten, int quality,
-            float sizeFactor, boolean needsExit) {
+            float sizeFactor, boolean needsExit, long requestId) {
         Intent processIntent = new Intent(context, ProcessingService.class);
         processIntent.putExtra(ProcessingService.SOURCE_URI,
                 sourceImageUri.toString());
@@ -157,6 +159,7 @@
                 preset.getJsonString(ImagePreset.JASON_SAVED));
         processIntent.putExtra(ProcessingService.SAVING, true);
         processIntent.putExtra(ProcessingService.EXIT, needsExit);
+        processIntent.putExtra(ProcessingService.REQUEST_ID, requestId);
         if (doFlatten) {
             processIntent.putExtra(ProcessingService.FLATTEN, true);
         }
@@ -182,13 +185,13 @@
 
     @Override
     public void onDestroy() {
-        tearDownPipeline();
         mProcessingTaskController.quit();
+        tearDownPipeline();
+        MasterImage.setMaster(null);
     }
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        mNeedsAlive = true;
         if (intent != null && intent.getBooleanExtra(SAVING, false)) {
             // we save using an intent to keep the service around after the
             // activity has been destroyed.
@@ -200,6 +203,7 @@
             float sizeFactor = intent.getFloatExtra(SIZE_FACTOR, 1);
             boolean flatten = intent.getBooleanExtra(FLATTEN, false);
             boolean exit = intent.getBooleanExtra(EXIT, false);
+            long requestId = intent.getLongExtra(REQUEST_ID, -1);
             Uri sourceUri = Uri.parse(source);
             Uri selectedUri = null;
             if (selected != null) {
@@ -211,11 +215,9 @@
             }
             ImagePreset preset = new ImagePreset();
             preset.readJsonFromString(presetJson);
-            mNeedsAlive = false;
-            mSaving = true;
             handleSaveRequest(sourceUri, selectedUri, destinationFile, preset,
                     MasterImage.getImage().getHighresImage(),
-                    flatten, quality, sizeFactor, exit);
+                    flatten, quality, sizeFactor, exit, requestId);
         }
         return START_REDELIVER_INTENT;
     }
@@ -225,24 +227,36 @@
         return mBinder;
     }
 
-    public void onStart() {
-        mNeedsAlive = true;
-        if (!mSaving && mFiltershowActivity != null) {
-            mFiltershowActivity.updateUIAfterServiceStarted();
+
+    //a lot of FilterShowActivity 's running instances bind to this service(only one instance)
+    //use broadcast result to notify FilterShowActivity 's instances to update UI
+    private void broadcastState(String action, Bundle bundle) {
+        Intent intent = new Intent();
+        intent.setAction(action);
+        if (bundle != null) {
+            intent.putExtras(bundle);
         }
+        sendBroadcast(intent);
     }
 
     public void handleSaveRequest(Uri sourceUri, Uri selectedUri,
             File destinationFile, ImagePreset preset, Bitmap previewImage,
-            boolean flatten, int quality, float sizeFactor, boolean exit) {
+            boolean flatten, int quality, float sizeFactor, boolean exit, long requestId) {
         mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
         mNotifyMgr.cancelAll();
 
-        mBuilder =
-                new Notification.Builder(this)
-                        .setSmallIcon(R.drawable.filtershow_button_fx)
-                        .setContentTitle(getString(R.string.filtershow_notification_label))
-                        .setContentText(getString(R.string.filtershow_notification_message));
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            String channelId = "GallerySavingRequest";
+            NotificationChannel channel = new NotificationChannel(channelId, channelId,
+                    NotificationManager.IMPORTANCE_DEFAULT);
+            mNotifyMgr.createNotificationChannel(channel);
+            mBuilder = new Notification.Builder(this, channelId);
+        } else {
+            mBuilder = new Notification.Builder(this);
+        }
+        mBuilder.setSmallIcon(R.drawable.filtershow_button_fx)
+                .setContentTitle(getString(R.string.filtershow_notification_label))
+                .setContentText(getString(R.string.filtershow_notification_message));
 
         startForeground(mNotificationId, mBuilder.build());
 
@@ -251,7 +265,7 @@
         // Process the image
 
         mImageSavingTask.saveImage(sourceUri, selectedUri, destinationFile,
-                preset, previewImage, flatten, quality, sizeFactor, exit);
+                preset, previewImage, flatten, quality, sizeFactor, exit, requestId);
     }
 
     public void updateNotificationWithBitmap(Bitmap bitmap) {
@@ -264,13 +278,9 @@
         mNotifyMgr.notify(mNotificationId, mBuilder.build());
     }
 
-    public void completePreviewSaveImage(Uri result, boolean exit) {
-        if (exit && !mNeedsAlive && !mFiltershowActivity.isSimpleEditAction()) {
-            mFiltershowActivity.completeSaveImage(result);
-        }
-    }
+    public void completeSaveImage(Uri result, long requestId,
+                                  boolean exit, boolean releaseDualCam) {
 
-    public void completeSaveImage(Uri result, boolean exit) {
         if (SHOW_IMAGE) {
             // TODO: we should update the existing image in Gallery instead
             Intent viewImage = new Intent(Intent.ACTION_VIEW, result);
@@ -278,23 +288,18 @@
             startActivity(viewImage);
         }
         mNotifyMgr.cancel(mNotificationId);
-        if (!exit) {
-            stopForeground(true);
-            stopSelf();
-            return;
-        }
         stopForeground(true);
         stopSelf();
-        if (mNeedsAlive) {
-            // If the app has been restarted while we were saving...
-            mFiltershowActivity.updateUIAfterServiceStarted();
-        } else if (exit || mFiltershowActivity.isSimpleEditAction()) {
+        if (exit) {
             // terminate now
-            mFiltershowActivity.completeSaveImage(result);
+            Bundle bundle = new Bundle();
+            bundle.putString(KEY_URL, result == null ? null : result.toString());
+            bundle.putLong(KEY_REQUEST_ID, requestId);
+            broadcastState(SAVE_IMAGE_COMPLETE_ACTION, bundle);
         }
     }
 
-    private void setupPipeline() {
+    public void setupPipeline() {
         Resources res = getResources();
         FiltersManager.setResources(res);
         CachingPipeline.createRenderscriptContext(this);
@@ -304,12 +309,38 @@
         filtersManager.addBorders(this);
         filtersManager.addTools(this);
         filtersManager.addEffects();
+        filtersManager.addDualCam(this);
+        filtersManager.addMakeups(this);
+        filtersManager.addTrueScanner();
+        filtersManager.addHazeBuster();
+        filtersManager.addSeeStraight();
+        filtersManager.addTruePortrait(this);
+        filtersManager.addFilterPreset(this);
+        filtersManager.addWaterMarks(this);
+        filtersManager.addLocations(this);
+        filtersManager.addTimes(this);
+        filtersManager.addWeather(this);
+        filtersManager.addEmotions(this);
+        filtersManager.addFoods(this);
 
         FiltersManager highresFiltersManager = FiltersManager.getHighresManager();
         highresFiltersManager.addLooks(this);
         highresFiltersManager.addBorders(this);
         highresFiltersManager.addTools(this);
         highresFiltersManager.addEffects();
+        highresFiltersManager.addDualCam(this);
+//        highresFiltersManager.addMakeups(this);
+        highresFiltersManager.addTrueScanner();
+        highresFiltersManager.addHazeBuster();
+        highresFiltersManager.addSeeStraight();
+        highresFiltersManager.addTruePortrait(this);
+        highresFiltersManager.addFilterPreset(this);
+        highresFiltersManager.addWaterMarks(this);
+        highresFiltersManager.addLocations(this);
+        highresFiltersManager.addTimes(this);
+        highresFiltersManager.addWeather(this);
+        highresFiltersManager.addEmotions(this);
+        highresFiltersManager.addFoods(this);
     }
 
     private void tearDownPipeline() {
@@ -322,6 +353,6 @@
     }
 
     static {
-        System.loadLibrary("jni_filtershow_filters");
+        System.loadLibrary("jni_gallery_filters");
     }
 }
diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
index 4cb9e5a..300dfe9 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java
@@ -84,6 +84,10 @@
             request.setBounds(bounds);
             request.setDestination(destination);
             passedPreset.setPartialRendering(true, bounds);
+        } else if (type == GEOMETRY_RENDERING ||
+                type == FILTERS_RENDERING) {
+            passedPreset.setDoApplyGeometry(preset.getDoApplyGeometry());
+            passedPreset.setDoApplyFilters(preset.getDoApplyFilters());
         }
 
         request.setImagePreset(passedPreset);
diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
index f243aa6..25d480a 100644
--- a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
+++ b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java
@@ -79,5 +79,24 @@
         return false;
     }
 
+    public synchronized void reset() {
+        if(mProducer != null) {
+            mProducer.remove();
+        }
+        mProducer = null;
+
+        if(mConsumer != null) {
+            mConsumer.remove();
+        }
+        mConsumer = null;
+
+        if(mIntermediate != null) {
+            mIntermediate.remove();
+        }
+        mIntermediate = null;
+
+        mNeedsSwap = false;
+        mNeedsRepaint = true;
+    }
 }
 
diff --git a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
old mode 100644
new mode 100755
index 81de6cf..1bfe2d1
--- a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
+++ b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java
@@ -16,50 +16,73 @@
 
 package com.android.gallery3d.filtershow.presets;
 
+import android.app.Dialog;
+import android.content.DialogInterface;
 import android.os.Bundle;
-import androidx.fragment.app.DialogFragment;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.ListView;
-import com.android.gallery3d.R;
+import android.view.Window;
+import android.widget.CheckBox;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
+import com.android.gallery3d.ui.BaseDialogFragment;
+import com.android.gallery3d.util.GalleryUtils;
 
-public class PresetManagementDialog extends DialogFragment implements View.OnClickListener {
-    private UserPresetsAdapter mAdapter;
-    private EditText mEditText;
+//import static com.android.gallery3d.filtershow.FilterShowActivity.SELECT_FILTER;
+
+public class PresetManagementDialog extends BaseDialogFragment implements View.OnClickListener {
+    private CheckBox mCheckBox;
+    private boolean checked;
+    private boolean mDismissInternal = true;
+    private DialogInterface.OnDismissListener mDialogDismissListener;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
-        View view = inflater.inflate(R.layout.filtershow_presets_management_dialog, container);
-
-        FilterShowActivity activity = (FilterShowActivity) getActivity();
-        mAdapter = activity.getUserPresetsAdapter();
-        mEditText = (EditText) view.findViewById(R.id.editView);
+        View view = inflater.inflate(R.layout.filtershow_presets_dialog, container);
+        mCheckBox = (CheckBox) view.findViewById(R.id.filtershow_check_box);
         view.findViewById(R.id.cancel).setOnClickListener(this);
         view.findViewById(R.id.ok).setOnClickListener(this);
-        getDialog().setTitle(getString(R.string.filtershow_save_preset));
+        view.findViewById(R.id.filtershow_check_box).setOnClickListener(this);
         return view;
     }
 
     @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        return dialog;
+    }
+
+    public void setOnDismissListener(DialogInterface.OnDismissListener listener) {
+        mDialogDismissListener = listener;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if ((mDialogDismissListener != null) && mDismissInternal) {
+            mDialogDismissListener.onDismiss(dialog);
+        }
+        mDismissInternal = true;
+    }
+
+    public void setDismissFlag(boolean isInternal) {
+        mDismissInternal = isInternal;
+    }
+
+    @Override
     public void onClick(View v) {
         FilterShowActivity activity = (FilterShowActivity) getActivity();
         switch (v.getId()) {
             case R.id.cancel:
-                mAdapter.clearChangedRepresentations();
-                mAdapter.clearDeletedRepresentations();
-                activity.updateUserPresetsFromAdapter(mAdapter);
                 dismiss();
                 break;
             case R.id.ok:
-                String text = String.valueOf(mEditText.getText());
-                activity.saveCurrentImagePreset(text);
-                mAdapter.updateCurrent();
-                activity.updateUserPresetsFromAdapter(mAdapter);
+                checked = mCheckBox.isChecked();
+                GalleryUtils.setBooleanPref(activity,activity.getString(R.string.pref_filtergenerator_intro_show_key),checked);
+                activity.onMediaPickerStarted ();
                 dismiss();
                 break;
         }
diff --git a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java b/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java
index dab9ea4..be48ccc 100644
--- a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java
+++ b/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java
@@ -25,7 +25,7 @@
 import android.widget.EditText;
 import android.widget.ImageButton;
 import android.widget.ImageView;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.category.Action;
 import com.android.gallery3d.filtershow.category.CategoryView;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
diff --git a/src/com/android/gallery3d/filtershow/state/StateAdapter.java b/src/com/android/gallery3d/filtershow/state/StateAdapter.java
index 5225852..cf3499d 100644
--- a/src/com/android/gallery3d/filtershow/state/StateAdapter.java
+++ b/src/com/android/gallery3d/filtershow/state/StateAdapter.java
@@ -21,7 +21,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
diff --git a/src/com/android/gallery3d/filtershow/state/StatePanel.java b/src/com/android/gallery3d/filtershow/state/StatePanel.java
index 039bc2c..7a4040b 100644
--- a/src/com/android/gallery3d/filtershow/state/StatePanel.java
+++ b/src/com/android/gallery3d/filtershow/state/StatePanel.java
@@ -24,7 +24,7 @@
 import android.view.ViewGroup;
 import android.widget.ImageButton;
 import android.widget.LinearLayout;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.category.MainPanel;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.util.FilterShowHelper;
@@ -48,7 +48,9 @@
 
         View panel = mMainView.findViewById(R.id.listStates);
         track = (StatePanelTrack) panel;
-        track.setAdapter(MasterImage.getImage().getState());
+        StateAdapter imageStateAdapter = MasterImage.getImage().getState();
+        if (imageStateAdapter == null) return null;
+        track.setAdapter(imageStateAdapter);
         mToggleVersionsPanel = (ImageButton) mMainView.findViewById(R.id.toggleVersionsPanel);
         if (FilterShowHelper.shouldUseVersions()) {
             if (mToggleVersionsPanel.getVisibility() == View.GONE
diff --git a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java
index 4ddb363..105c671 100644
--- a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java
+++ b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java
@@ -31,7 +31,7 @@
 import android.view.ViewGroup;
 import android.widget.Adapter;
 import android.widget.LinearLayout;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.editors.ImageOnlyEditor;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
diff --git a/src/com/android/gallery3d/filtershow/state/StateView.java b/src/com/android/gallery3d/filtershow/state/StateView.java
index a43cd47..9035b8a 100644
--- a/src/com/android/gallery3d/filtershow/state/StateView.java
+++ b/src/com/android/gallery3d/filtershow/state/StateView.java
@@ -22,7 +22,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.LinearLayout;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.category.SwipableView;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
diff --git a/src/com/android/gallery3d/filtershow/tools/DualCameraEffect.java b/src/com/android/gallery3d/filtershow/tools/DualCameraEffect.java
new file mode 100644
index 0000000..99bc4e9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/DualCameraEffect.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.util.Log;
+import android.util.Size;
+
+public class DualCameraEffect {
+    private static final String TAG = "DualCameraEffect";
+
+    // following constants should be consistent with jni code
+    public static final int INPUT = 0;
+    public static final int REFOCUS_CIRCLE = 1;
+    public static final int REFOCUS_HEXAGON = 2;
+    public static final int REFOCUS_STAR = 3;
+    public static final int SKETCH = 4;
+    public static final int HALO = 5;
+    public static final int MOTION_BLUR = 6;
+    public static final int FUSION_FOREGROUND = 7;
+    public static final int ZOOM_BLUR = 8;
+    public static final int BLACK_WHITE = 9;
+    public static final int WHITEBOARD = 10;
+    public static final int BLACKBOARD = 11;
+    public static final int POSTERIZE = 12;
+    public static final int NEGATIVE = 13;
+
+    public static final float DEFAULT_BRIGHTNESS_INTENSITY = 1.0f;
+
+    static {
+        try {
+            System.loadLibrary("jni_dualcamera");
+            loaded = true;
+            Log.v(TAG, "successfully loaded dual camera lib");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "failed to load dual camera lib");
+            loaded = false;
+        }
+    }
+
+    private static boolean loaded;
+    private static DualCameraEffect instance;
+
+    private int[] mRoi;
+    private int mWidth;
+    private int mHeight;
+
+    private DualCameraEffect() {}
+
+    public static boolean isSupported() {
+        return loaded;
+    }
+
+    public static synchronized DualCameraEffect getInstance() {
+        if (instance == null) {
+            instance = new DualCameraEffect();
+        }
+        return instance;
+    }
+
+    public boolean initialize(Bitmap primary, Bitmap depthMap, int[] roi, int width, int height,
+            float brIntensity) {
+        boolean ok = init(primary, depthMap, roi, width, height, brIntensity);
+        if (ok) {
+            mRoi = roi;
+            mWidth = width;
+            mHeight = height;
+        }
+        return ok;
+    }
+
+    public void map(Point point) {
+        point.x = (point.x - mRoi[0]) * mWidth / mRoi[2];
+        point.y = (point.y - mRoi[1]) * mHeight / mRoi[3];
+    }
+
+    public Size size() {
+        return new Size(mWidth, mHeight);
+    }
+
+    native private boolean init(Bitmap primary, Bitmap depthMap, int[] roi, int width, int height,
+            float brIntensity);
+
+    native public void release();
+
+    native public boolean render(int effect, int focusPointX, int focusPointY, Bitmap out,
+            float intensity);
+
+    public boolean render(int effect, int focusPointX, int focusPointY, Bitmap out) {
+        return render(effect, focusPointX, focusPointY, out, 0);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java
new file mode 100644
index 0000000..f95688d
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/FilterGeneratorNativeEngine.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import java.io.File;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Point;
+import android.util.Log;
+
+public class FilterGeneratorNativeEngine {
+    private static final String TAG = "FilterGeneratorNativeEngine";
+    static {
+        try {
+            System.loadLibrary("jni_filtergenerator");
+            mLibLoaded = true;
+            Log.v(TAG, "successfully loaded filter generator lib");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "failed to load filter generator lib");
+            mLibLoaded = false;
+        }
+    }
+
+    private static boolean mLibLoaded;
+
+    private static FilterGeneratorNativeEngine mInstance;
+
+    private FilterGeneratorNativeEngine() {}
+
+    public static void createInstance() {
+        if(mInstance == null) {
+            mInstance = new FilterGeneratorNativeEngine();
+        }
+    }
+
+    public static FilterGeneratorNativeEngine getInstance() {
+        createInstance();
+        return mInstance;
+    }
+
+    public boolean isLibLoaded() {
+        return mLibLoaded;
+    }
+
+    native public boolean filterGeneratorProcess (Bitmap srcRGBA, Bitmap refRGBA, Bitmap dstRGBA);
+
+}
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
old mode 100644
new mode 100755
index 17d698f..433af8b
--- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java
+++ b/src/com/android/gallery3d/filtershow/tools/SaveImage.java
@@ -16,12 +16,28 @@
 
 package com.android.gallery3d.filtershow.tools;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.sql.Date;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.database.Cursor;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.net.Uri;
 import android.os.Environment;
 import android.provider.MediaStore;
@@ -30,28 +46,24 @@
 import android.util.Log;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.GalleryActivity;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.exif.ExifInterface;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.cache.ImageLoader;
+import com.android.gallery3d.filtershow.filters.FilterDualCamFusionRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FilterRepresentation;
+import com.android.gallery3d.filtershow.filters.FilterTruePortraitFusionRepresentation;
 import com.android.gallery3d.filtershow.filters.FiltersManager;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.CachingPipeline;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 import com.android.gallery3d.filtershow.pipeline.ProcessingService;
 import com.android.gallery3d.util.XmpUtilHelper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.TimeZone;
+import androidx.heifwriter.HeifWriter;
 
 /**
  * Handles saving edited photo
@@ -77,10 +89,12 @@
     private static final String POSTFIX_JPG = ".jpg";
     private static final String AUX_DIR_NAME = ".aux";
 
+    public static final String POSTFIX_HEIC = ".heic";
+
     private final Context mContext;
     private final Uri mSourceUri;
-    private final Callback mCallback;
     private final File mDestinationFile;
+    private final Callback mCallback;
     private final Uri mSelectedImageUri;
     private final Bitmap mPreviewImage;
 
@@ -163,6 +177,9 @@
         if (hasPanoPrefix(context, sourceUri)) {
             return new File(saveDirectory, PREFIX_PANO + filename + POSTFIX_JPG);
         }
+        if (hasHeifPostfix(context, sourceUri)) {
+            return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_HEIC);
+        }
         return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG);
     }
 
@@ -179,12 +196,12 @@
         querySourceFromContentResolver(contentResolver,
                 srcContentUri, queryProjection,
                 new ContentResolverQueryCallback() {
-                    @Override
-                    public void onCursorResult(Cursor cursor) {
-                        fullPath[0] = cursor.getString(0);
-                    }
-                }
-        );
+            @Override
+            public void onCursorResult(Cursor cursor) {
+                fullPath[0] = cursor.getString(0);
+            }
+        });
+
         if (fullPath[0] != null) {
             // Construct the auxiliary directory given the source file's path.
             // Then select and delete all the files starting with the same name
@@ -247,7 +264,7 @@
         if (mimeType == null) {
             mimeType = ImageLoader.getMimeType(mSelectedImageUri);
         }
-        if (mimeType.equals(ImageLoader.JPEG_MIME_TYPE)) {
+        if (ImageLoader.JPEG_MIME_TYPE.equals(mimeType)) {
             InputStream inStream = null;
             try {
                 inStream = mContext.getContentResolver().openInputStream(source);
@@ -256,6 +273,8 @@
                 Log.w(LOGTAG, "Cannot find file: " + source, e);
             } catch (IOException e) {
                 Log.w(LOGTAG, "Cannot read exif for: " + source, e);
+            } catch (NullPointerException e) {
+                Log.w(LOGTAG, "Invalid exif data for: " + source, e);
             } finally {
                 Utils.closeSilently(inStream);
             }
@@ -263,7 +282,7 @@
         return exif;
     }
 
-    public boolean putExifData(File file, ExifInterface exif, Bitmap image,
+    public static boolean putExifData(File file, ExifInterface exif, Bitmap image,
             int jpegCompressQuality) {
         boolean ret = false;
         OutputStream s = null;
@@ -285,6 +304,34 @@
         return ret;
     }
 
+    public static boolean putHeifData(File file, ExifInterface exif, Bitmap image,
+                                      int compressQuality) {
+        boolean ret = false;
+        String path = file.getAbsolutePath();
+        if (image != null) {
+            try {
+                HeifWriter.Builder builder =
+                        new HeifWriter.Builder(path,image.getWidth(), image.getHeight(),
+                                HeifWriter.INPUT_MODE_BITMAP);
+                builder.setQuality(compressQuality);
+                builder.setMaxImages(1);
+                builder.setPrimaryIndex(0);
+                builder.setRotation(0);
+                HeifWriter heifWriter = builder.build();
+                heifWriter.start();
+                heifWriter.addBitmap(image);
+                heifWriter.stop(3000);
+                heifWriter.close();
+                ret = true;
+            } catch (IOException|IllegalStateException e) {
+                e.printStackTrace();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return ret;
+    }
+
     private Uri resetToOriginalImageIfNeeded(ImagePreset preset, boolean doAuxBackup) {
         Uri uri = null;
         if (!preset.hasModifications()) {
@@ -342,27 +389,46 @@
         int num_tries = 0;
         int sampleSize = 1;
 
+        File sourceFile = getLocalFileFromUri(mContext,mSourceUri);
+        boolean saveHeif = sourceFile.getName().endsWith(POSTFIX_HEIC);
+
         // If necessary, move the source file into the auxiliary directory,
         // newSourceUri is then pointing to the new location.
         // If no file is moved, newSourceUri will be the same as mSourceUri.
         Uri newSourceUri = mSourceUri;
-        if (!flatten) {
-            newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile);
-        }
+        /*
+         * if (!flatten) { newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); }
+         */
 
         Uri savedUri = mSelectedImageUri;
         if (mPreviewImage != null) {
+            Bitmap previewBmp;
+            // Check for Fusion
+            FilterFusionRepresentation fusionRep = findFusionRepresentation(preset);
+            boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
+            if(hasFusion) {
+                previewBmp = flattenFusion(mContext, Uri.parse(fusionRep.getUnderlay()), mPreviewImage,
+                        Math.max(mPreviewImage.getWidth(), mPreviewImage.getHeight()), 0);
+                // If we fail to flatten, save original image
+                if(previewBmp == null) {
+                    previewBmp = mPreviewImage;
+                    hasFusion = false;
+                }
+            } else {
+                previewBmp = mPreviewImage;
+            }
+
             if (flatten) {
                 Object xmp = getPanoramaXMPData(newSourceUri, preset);
                 ExifInterface exif = getExifData(newSourceUri);
                 long time = System.currentTimeMillis();
                 updateExifData(exif, time);
-                if (putExifData(mDestinationFile, exif, mPreviewImage, quality)) {
+                if (putExifData(mDestinationFile, exif, previewBmp, quality)) {
                     putPanoramaXMPData(mDestinationFile, xmp);
                     ContentValues values = getContentValues(mContext, mSelectedImageUri, mDestinationFile, time);
                     Object result = mContext.getContentResolver().insert(
                             Images.Media.EXTERNAL_CONTENT_URI, values);
-
+                    Log.d(GalleryActivity.QSST, "image exported successfully");
                 }
             } else {
                 Object xmp = getPanoramaXMPData(newSourceUri, preset);
@@ -370,7 +436,7 @@
                 long time = System.currentTimeMillis();
                 updateExifData(exif, time);
                 // If we succeed in writing the bitmap as a jpeg, return a uri.
-                if (putExifData(mDestinationFile, exif, mPreviewImage, quality)) {
+                if (putExifData(mDestinationFile, exif, previewBmp, quality)) {
                     putPanoramaXMPData(mDestinationFile, xmp);
                     // mDestinationFile will save the newSourceUri info in the XMP.
                     if (!flatten) {
@@ -380,9 +446,16 @@
                     // After this call, mSelectedImageUri will be actually
                     // pointing at the new file mDestinationFile.
                     savedUri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri,
-                            mDestinationFile, time, !flatten);
+                            mDestinationFile, time, false);
                 }
             }
+
+            if(hasFusion) {
+                // recycle bitmap
+                previewBmp.recycle();
+                previewBmp = null;
+            }
+
             if (mCallback != null) {
                 mCallback.onPreviewSaved(savedUri);
             }
@@ -413,6 +486,19 @@
                         "Saving");
 
                 bitmap = pipeline.renderFinalImage(bitmap, preset);
+
+                // Check for Fusion
+                FilterFusionRepresentation fusionRep = findFusionRepresentation(preset);
+                boolean hasFusion = (fusionRep != null && fusionRep.hasUnderlay());
+                if(hasFusion) {
+                    Bitmap underlay = flattenFusion(mContext,
+                            Uri.parse(fusionRep.getUnderlay()), bitmap, 0, sampleSize);
+                    if(underlay != null) {
+                        bitmap.recycle();
+                        bitmap = underlay;
+                    }
+                }
+
                 updateProgress();
 
                 Object xmp = getPanoramaXMPData(newSourceUri, preset);
@@ -424,10 +510,17 @@
                 updateProgress();
 
                 // If we succeed in writing the bitmap as a jpeg, return a uri.
-                if (putExifData(mDestinationFile, exif, bitmap, quality)) {
-                    putPanoramaXMPData(mDestinationFile, xmp);
+                boolean success = false;
+                if (saveHeif) {
+                    success = putHeifData(mDestinationFile, exif, bitmap, quality);
+                } else {
+                    success = putExifData(mDestinationFile, exif, bitmap, quality);
+                }
+                if (success) {
+                    if (!saveHeif)
+                        putPanoramaXMPData(mDestinationFile, xmp);
                     // mDestinationFile will save the newSourceUri info in the XMP.
-                    if (!flatten) {
+                    if (!flatten && !saveHeif) {
                         XmpPresets.writeFilterXMP(mContext, newSourceUri,
                                 mDestinationFile, preset);
                         uri = updateFile(mContext, savedUri, mDestinationFile, time);
@@ -540,8 +633,12 @@
         if (preset.contains(FilterRepresentation.TYPE_TINYPLANET)){
             flatten = true;
         }
+
+        float scaleFactor = 1f;
+
         Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset,
-                destination, selectedImageUri, sourceImageUri, flatten, 90, 1f, true);
+                destination, selectedImageUri, sourceImageUri, flatten, 90,
+                scaleFactor, true, filterShowActivity.getRequestId());
 
         filterShowActivity.startService(processIntent);
 
@@ -593,7 +690,7 @@
      * @return The file object. Return null if srcUri is invalid or not a local
      * file.
      */
-    private static File getLocalFileFromUri(Context context, Uri srcUri) {
+    public static File getLocalFileFromUri(Context context, Uri srcUri) {
         if (srcUri == null) {
             Log.e(LOGTAG, "srcUri is null.");
             return null;
@@ -613,13 +710,13 @@
                 querySource(context, srcUri, new String[] {
                         ImageColumns.DATA
                 },
-                        new ContentResolverQueryCallback() {
+                new ContentResolverQueryCallback() {
 
-                            @Override
-                            public void onCursorResult(Cursor cursor) {
-                                file[0] = new File(cursor.getString(0));
-                            }
-                        });
+                    @Override
+                    public void onCursorResult(Cursor cursor) {
+                        file[0] = new File(cursor.getString(0));
+                    }
+                });
             }
         } else if (scheme.equals(ContentResolver.SCHEME_FILE)) {
             file[0] = new File(srcUri.getPath());
@@ -654,6 +751,11 @@
         return name != null && name.startsWith(PREFIX_PANO);
     }
 
+    private static boolean hasHeifPostfix(Context context, Uri src) {
+        String name = getTrueFilename(context,src);
+        return name != null && name.endsWith(POSTFIX_HEIC);
+    }
+
     /**
      * If the <code>sourceUri</code> is a local content Uri, update the
      * <code>sourceUri</code> to point to the <code>file</code>.
@@ -688,19 +790,26 @@
 
     public static Uri updateFile(Context context, Uri sourceUri, File file, long time) {
         final ContentValues values = getContentValues(context, sourceUri, file, time);
+        if (file.getName().endsWith(".heic")) {
+            values.put(Images.Media.MIME_TYPE, "image/heif");
+        }
         context.getContentResolver().update(sourceUri, values, null, null);
         return sourceUri;
     }
 
     private static ContentValues getContentValues(Context context, Uri sourceUri,
-                                                  File file, long time) {
+            File file, long time) {
         final ContentValues values = new ContentValues();
 
         time /= 1000;
         values.put(Images.Media.TITLE, file.getName());
         values.put(Images.Media.DISPLAY_NAME, file.getName());
-        values.put(Images.Media.MIME_TYPE, "image/jpeg");
-        values.put(Images.Media.DATE_TAKEN, time);
+        if (file.getName().endsWith(".heic")) {
+            values.put(Images.Media.MIME_TYPE, "image/heif");
+        } else {
+            values.put(Images.Media.MIME_TYPE, "image/jpeg");
+        }
+        values.put(Images.Media.DATE_TAKEN, time * 1000);
         values.put(Images.Media.DATE_MODIFIED, time);
         values.put(Images.Media.DATE_ADDED, time);
         values.put(Images.Media.ORIENTATION, 0);
@@ -718,20 +827,20 @@
         SaveImage.querySource(context, sourceUri, projection,
                 new ContentResolverQueryCallback() {
 
-                    @Override
-                    public void onCursorResult(Cursor cursor) {
-                        values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
+            @Override
+            public void onCursorResult(Cursor cursor) {
+                values.put(Images.Media.DATE_TAKEN, cursor.getLong(0));
 
-                        double latitude = cursor.getDouble(1);
-                        double longitude = cursor.getDouble(2);
-                        // TODO: Change || to && after the default location
-                        // issue is fixed.
-                        if ((latitude != 0f) || (longitude != 0f)) {
-                            values.put(Images.Media.LATITUDE, latitude);
-                            values.put(Images.Media.LONGITUDE, longitude);
-                        }
-                    }
-                });
+                double latitude = cursor.getDouble(1);
+                double longitude = cursor.getDouble(2);
+                // TODO: Change || to && after the default location
+                // issue is fixed.
+                if ((latitude != 0f) || (longitude != 0f)) {
+                    values.put(Images.Media.LATITUDE, latitude);
+                    values.put(Images.Media.LONGITUDE, longitude);
+                }
+            }
+        });
         return values;
     }
 
@@ -747,4 +856,62 @@
         return false;
     }
 
+    private FilterFusionRepresentation findFusionRepresentation(ImagePreset preset) {
+        FilterDualCamFusionRepresentation dcRepresentation =
+                (FilterDualCamFusionRepresentation)preset.getFilterWithSerializationName(
+                        FilterDualCamFusionRepresentation.SERIALIZATION_NAME);
+        FilterTruePortraitFusionRepresentation tpRepresentation =
+                (FilterTruePortraitFusionRepresentation)preset.getFilterWithSerializationName(
+                        FilterTruePortraitFusionRepresentation.SERIALIZATION_NAME);
+
+        FilterFusionRepresentation fusionRep = null;
+
+        if(dcRepresentation != null)
+            fusionRep = (FilterFusionRepresentation) dcRepresentation;
+        else if (tpRepresentation != null)
+            fusionRep = (FilterFusionRepresentation) tpRepresentation;
+
+        return fusionRep;
+    }
+
+    public static Bitmap flattenFusion(Context context, Uri underlayUri, Bitmap bitmap, int sizeConstraint, int sampleSize) {
+        // fusion. decode underlay image and get dest rect
+
+        Bitmap underlay = null;
+
+        if(sizeConstraint != 0) {
+            underlay = ImageLoader.loadConstrainedBitmap(underlayUri, context,
+                    sizeConstraint, null, false);
+        } else if (sampleSize != 0) {
+            underlay = ImageLoader.loadBitmapWithBackouts(context, underlayUri, sampleSize);
+        }
+
+        if(underlay != null) {
+            int ori = ImageLoader.getMetadataOrientation(context, underlayUri);
+            if (ori != ImageLoader.ORI_NORMAL) {
+                underlay = ImageLoader.orientBitmap(underlay, ori);
+            }
+            RectF destRect = new RectF();
+            Rect imageBounds = MasterImage.getImage().getImageBounds();
+            Rect underlayBounds = MasterImage.getImage().getFusionBounds();
+            float underlayScaleFactor = (float)underlay.getWidth()
+                    / (float)underlayBounds.width();
+
+            destRect.left = (imageBounds.left - underlayBounds.left) * underlayScaleFactor;
+            destRect.right = (imageBounds.right - underlayBounds.left) * underlayScaleFactor;
+            destRect.top = (imageBounds.top - underlayBounds.top) * underlayScaleFactor;
+            destRect.bottom = (imageBounds.bottom - underlayBounds.top) * underlayScaleFactor;
+
+            Canvas canvas = new Canvas(underlay);
+            Paint paint = new Paint();
+            paint.reset();
+            paint.setAntiAlias(true);
+            paint.setFilterBitmap(true);
+            paint.setDither(true);
+            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
+
+            canvas.drawBitmap(bitmap, null, destRect, paint);
+        }
+        return underlay;
+    }
 }
diff --git a/src/com/android/gallery3d/filtershow/tools/TruePortraitNativeEngine.java b/src/com/android/gallery3d/filtershow/tools/TruePortraitNativeEngine.java
new file mode 100644
index 0000000..4322bb9
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/tools/TruePortraitNativeEngine.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.tools;
+
+import java.util.Stack;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.Rect;
+import androidx.fragment.app.FragmentManager;
+import android.util.Log;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData;
+import com.android.gallery3d.filtershow.ui.AlertMsgDialog;
+
+public class TruePortraitNativeEngine {
+    private static final String TAG = "TruePortraitNativeEngine";
+    static {
+        try {
+            //System.loadLibrary("jni_trueportrait");
+            //mLibLoaded = true;
+            //Log.v(TAG, "successfully loaded true portrait lib");
+        } catch (UnsatisfiedLinkError e) {
+            Log.e(TAG, "failed to load true portrait lib");
+            mLibLoaded = false;
+        }
+    }
+
+    public static enum EffectType {
+        BLUR,
+        MOTION_BLUR,
+        HALO,
+        SKETCH
+    };
+
+    private static final int MASK_UPDATE_FOREGROUND = 0x7F000000;
+    private static final int MASK_UPDATE_BACKGROUND = 0x81000000;
+
+    private static boolean mLibLoaded = false;
+    private static TruePortraitNativeEngine mInstance;
+
+    private Bitmap mSketchBm;
+    private boolean mFacesDetected;
+    private Point mPreviewSize = new Point();
+    private Bitmap mUpdateBm;
+
+    private TruePortraitNativeEngine() {}
+
+    public static void createInstance() {
+        if(mInstance == null) {
+            mInstance = new TruePortraitNativeEngine();
+        }
+    }
+
+    public static TruePortraitNativeEngine getInstance() {
+        createInstance();
+        return mInstance;
+    }
+
+    public boolean isLibLoaded() {
+        return mLibLoaded;
+    }
+
+    public boolean init(Context context, Bitmap src, Rect[] faces) {
+        boolean result = false; 
+        if(nativeInit(src, faces.length, faces)) {
+            result = nativeGetPreviewSize(mPreviewSize);
+        }
+        if (result) {
+            mSketchBm = BitmapFactory.decodeResource(context.getResources(), R.raw.sketch_bm);
+        } else {
+            mSketchBm = null;
+        }
+        setFacesDetected(result);   
+        return result;
+    }
+
+    public void release() {
+        if(mUpdateBm != null) {
+            mUpdateBm.recycle();
+            mUpdateBm = null;
+        }
+
+        if(mSketchBm != null) {
+            mSketchBm.recycle();
+            mSketchBm = null;
+        }
+
+        nativeRelease();
+    }
+
+    public void setFacesDetected(boolean detected) {
+        mFacesDetected = detected;
+    }
+
+    public boolean facesDetected() {
+        return mFacesDetected;
+    }
+
+    public void showNoFaceDetectedDialog(FragmentManager fragmentManager) {
+        AlertMsgDialog dialog = new AlertMsgDialog(R.string.trueportrait, R.string.trueportrait_no_face);
+        dialog.show(fragmentManager, "tp_no_face");
+    }
+
+    public boolean applyEffect(EffectType type, int intensity, Bitmap outBm) {
+        boolean result = false;
+        switch(type) {
+        case BLUR:
+            result = nativeApplyBlur(intensity, outBm);
+            break;
+        case MOTION_BLUR:
+            result = nativeApplyMotionBlur(intensity, outBm);
+            break;
+        case HALO:
+            result = nativeApplyHalo(intensity, outBm);
+            break;
+        case SKETCH:
+            result = nativeApplySketch(outBm, mSketchBm);
+            break;
+        }
+
+        return result;
+    }
+
+    public Bitmap getMask() {
+        Bitmap mask = Bitmap.createBitmap(mPreviewSize.x, mPreviewSize.y, Config.ALPHA_8);
+        if(mask != null) {
+            nativeGetPreviewMask(mask);
+        }
+
+        return mask;
+    }
+
+    public Bitmap getPreview() {
+        Bitmap previewBm = Bitmap.createBitmap(mPreviewSize.x, mPreviewSize.y, Config.ARGB_8888);
+        if(previewBm != null) {
+            nativeGetPreviewImage(previewBm);
+        }
+
+        return previewBm;
+    }
+
+    public boolean updateMask(Stack<StrokeData> edits) {
+        if(mUpdateBm == null) {
+            mUpdateBm = Bitmap.createBitmap(mPreviewSize.x, mPreviewSize.y, Config.ALPHA_8);
+        }
+
+        mUpdateBm.eraseColor(Color.TRANSPARENT);
+        Canvas canvas = new Canvas(mUpdateBm);
+        for(StrokeData sd:edits) {
+            drawEdit(canvas, sd);
+        }
+        return nativeUpdatePreviewMask(mUpdateBm);
+    }
+
+    private void drawEdit(Canvas canvas, StrokeData sd) {
+        if (sd == null) {
+            return;
+        }
+        if (sd.mPath == null) {
+            return;
+        }
+        //  USER_INPUT_MASK_UNCHANGED_VALUE   = 0
+        //  USER_INPUT_MASK_BACKGROUND_VALUE  = 129
+        //  USER_INPUT_MASK_FOREGROUND_VALUE  = 127
+        Paint paint = new Paint();
+        paint.setAntiAlias(false);
+        paint.setStyle(Style.STROKE);
+        paint.setStrokeCap(Paint.Cap.ROUND);
+        if(sd.mColor == Color.TRANSPARENT)
+            paint.setColor(MASK_UPDATE_BACKGROUND);
+        else
+            paint.setColor(MASK_UPDATE_FOREGROUND);
+        paint.setStrokeWidth(sd.mRadius);
+
+        canvas.drawPath(sd.mPath, paint);
+    }
+
+    native public boolean nativeInit(Bitmap srcRGBA, int numFaces, Rect[] faces);
+
+    native public void nativeRelease();
+
+    native public boolean nativeGetPreviewSize(Point point);
+
+    native public boolean nativeGetPreviewImage(Bitmap outBm);
+
+    native public boolean nativeGetPreviewMask(Bitmap outBm);
+
+    native public boolean nativeUpdatePreviewMask(Bitmap mask);
+
+    native public boolean nativeApplyBlur(int intensity, Bitmap outBm);
+
+    native public boolean nativeApplyMotionBlur(int intensity, Bitmap outBm);
+
+    native public boolean nativeApplyHalo(int intensity, Bitmap outBm);
+
+    native public boolean nativeApplySketch(Bitmap outBm, Bitmap sketchBm);
+
+    native public boolean nativeGetForegroundImg(Bitmap outBm);
+}
diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
index 7095e74..dfb0bc2 100644
--- a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
+++ b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java
@@ -23,7 +23,7 @@
 import com.adobe.xmp.XMPException;
 import com.adobe.xmp.XMPMeta;
 import com.adobe.xmp.XMPMetaFactory;
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
diff --git a/src/com/android/gallery3d/filtershow/ui/AlertMsgDialog.java b/src/com/android/gallery3d/filtershow/ui/AlertMsgDialog.java
new file mode 100644
index 0000000..3a4ddac
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/ui/AlertMsgDialog.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.os.Bundle;
+
+import com.android.gallery3d.ui.BaseDialogFragment;
+
+import org.codeaurora.gallery.R;
+
+public class AlertMsgDialog extends BaseDialogFragment {
+    private int mTitleId = -1;
+    private int mMessageId = -1;
+
+    public AlertMsgDialog() {
+        super();
+        //this constructor should only be called by FragmentActivity.
+        //if called, it means dialog has been killed and is reconstructed.
+        //then don't show title and message.
+    }
+
+    public AlertMsgDialog(int titleId, int msgId) {
+        mTitleId = titleId;
+        mMessageId = msgId;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder ab = new AlertDialog.Builder(getActivity());
+        if (-1 != mTitleId) {
+            ab.setTitle(mTitleId);
+        }
+        if (-1 != mMessageId) {
+            ab.setMessage(mMessageId);
+        }
+        ab.setCancelable(false);
+        ab.setPositiveButton(R.string.ok, null);
+        return ab.create();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
new file mode 100644
index 0000000..73561e1
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/ui/DoNotShowAgainDialog.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.filtershow.ui;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.ui.BaseDialogFragment;
+import com.android.gallery3d.util.GalleryUtils;
+
+public class DoNotShowAgainDialog extends BaseDialogFragment {
+    private int mSharedPrefKeyId = -1;
+    private int mTitleId = -1;
+    private int mMessageId = -1;
+    private CheckBox mDoNotShowAgainChk;
+    private DialogInterface.OnClickListener mButtonClickListener;
+    private DialogInterface.OnDismissListener mDialogDismissListener;
+    private DialogInterface.OnCancelListener mCancelListener;
+
+    public DoNotShowAgainDialog() {
+        super();
+        //this constructor should only be called by FragmentActivity.
+        //if called, it means dialog has been killed and is reconstructed.
+        //then don't show title and message.
+    }
+
+    public DoNotShowAgainDialog(int titleId, int msgId, int sharedPrefKeyId) {
+        mTitleId = titleId;
+        mMessageId = msgId;
+        mSharedPrefKeyId = sharedPrefKeyId;
+        mButtonClickListener = null;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+        View view = inflater.inflate(R.layout.do_not_show_again_dialog, null);
+        TextView message = (TextView) view.findViewById(R.id.message);
+        if (-1 != mMessageId) {
+            message.setText(mMessageId);
+        }
+        mDoNotShowAgainChk = (CheckBox) view.findViewById(R.id.do_not_show_chk);
+
+        AlertDialog.Builder ab = new AlertDialog.Builder(getActivity());
+        if (-1 != mTitleId) {
+            ab.setTitle(mTitleId);
+        }
+        ab.setView(view);
+        ab.setCancelable(false);
+        ab.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+            public void onClick(DialogInterface dialog, int id) {
+                if (-1 != mSharedPrefKeyId) {
+                    Context context = getActivity();
+                    GalleryUtils.setBooleanPref(context,
+                            context.getString(mSharedPrefKeyId), mDoNotShowAgainChk.isChecked());
+                }
+                if(mButtonClickListener != null) mButtonClickListener.onClick(dialog, id);
+            }
+        });
+        return ab.create();
+    }
+
+    public void setOnOkButtonClickListener(DialogInterface.OnClickListener listener) {
+        mButtonClickListener = listener;
+    }
+
+    public void setOnDismissListener (DialogInterface.OnDismissListener listener) {
+        mDialogDismissListener = listener;
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        super.onDismiss(dialog);
+        if (mDialogDismissListener != null) {
+            mDialogDismissListener.onDismiss(dialog);
+        }
+    }
+
+    public void setOnCancelListener(DialogInterface.OnCancelListener listener) {
+        mCancelListener = listener;
+    }
+
+    @Override
+    public void onCancel(DialogInterface dialog) {
+        super.onCancel(dialog);
+        if (mCancelListener != null) {
+            mCancelListener.onCancel(dialog);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+    }
+}
diff --git a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
old mode 100644
new mode 100755
index 9f726b4..419d6bc
--- a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
+++ b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java
@@ -16,34 +16,35 @@
 
 package com.android.gallery3d.filtershow.ui;
 
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
-import androidx.fragment.app.DialogFragment;
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.EditText;
 import android.widget.SeekBar;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.filtershow.FilterShowActivity;
 import com.android.gallery3d.filtershow.imageshow.MasterImage;
 import com.android.gallery3d.filtershow.pipeline.ImagePreset;
 import com.android.gallery3d.filtershow.pipeline.ProcessingService;
 import com.android.gallery3d.filtershow.tools.SaveImage;
+import com.android.gallery3d.ui.BaseDialogFragment;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 
-public class ExportDialog extends DialogFragment implements View.OnClickListener,
-        SeekBar.OnSeekBarChangeListener {
+public class ExportDialog extends BaseDialogFragment implements SeekBar.OnSeekBarChangeListener {
     SeekBar mSeekBar;
     TextView mSeekVal;
     EditText mWidthText;
@@ -90,11 +91,45 @@
     }
 
     @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
         mHandler = new Handler(getActivity().getMainLooper());
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        View view = initCustomLayout();
+        builder.setView(view);
+        builder.setTitle(R.string.export_flattened);
+        builder.setPositiveButton(R.string.done,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int id) {
+                        FilterShowActivity activity = (FilterShowActivity) getActivity();
+                        Uri sourceUri = MasterImage.getImage().getUri();
+                        File dest = SaveImage.getNewFile(activity, activity.getSelectedImageUri());
+                        float scaleFactor = mExportWidth / (mOriginalBounds == null ? 1f :
+                                (float) mOriginalBounds.width());
+                        if (!activity.isWaterMarked()) {
+                            Intent processIntent = ProcessingService.getSaveIntent(activity,
+                                    MasterImage.getImage().getPreset(), dest,
+                                    activity.getSelectedImageUri(), sourceUri, true,
+                                    mSeekBar.getProgress(), scaleFactor, false, -1);
+                            activity.startService(processIntent);
+                        } else {
+                            activity.getSaveWaterMark().saveImage(activity,
+                                    MasterImage.getImage().getHighresImage(),
+                                    activity.getSelectedImageUri(), null, mSeekBar.getProgress(),
+                                    scaleFactor, true);
+                        }
+                    }
+                });
+        builder.setNegativeButton(R.string.cancel, null);
 
-        View view = inflater.inflate(R.layout.filtershow_export_dialog, container);
+        updateCompressionFactor();
+        updateSize();
+        return builder.create();
+    }
+
+    private View initCustomLayout() {
+        LayoutInflater inflater = getActivity().getLayoutInflater();
+        View view = inflater.inflate(R.layout.filtershow_export_dialog, null);
         mSeekBar = (SeekBar) view.findViewById(R.id.qualitySeekBar);
         mSeekVal = (TextView) view.findViewById(R.id.qualityTextView);
         mSliderLabel = getString(R.string.quality) + ": ";
@@ -107,8 +142,16 @@
 
         mOriginalBounds = MasterImage.getImage().getOriginalBounds();
         ImagePreset preset = MasterImage.getImage().getPreset();
+        if (mOriginalBounds == null || preset == null) return null;
         mOriginalBounds = preset.finalGeometryRect(mOriginalBounds.width(),
                 mOriginalBounds.height());
+        if (preset != null) {
+            mOriginalBounds = preset.finalGeometryRect(mOriginalBounds.width(),
+                    mOriginalBounds.height());
+        }
+        if (mOriginalBounds == null) {
+            return null;
+        }
         mRatio = mOriginalBounds.width() / (float) mOriginalBounds.height();
         mWidthText.setText("" + mOriginalBounds.width());
         mHeightText.setText("" + mOriginalBounds.height());
@@ -116,13 +159,6 @@
         mExportHeight = mOriginalBounds.height();
         mWidthText.addTextChangedListener(new Watcher(mWidthText));
         mHeightText.addTextChangedListener(new Watcher(mHeightText));
-
-        view.findViewById(R.id.cancel).setOnClickListener(this);
-        view.findViewById(R.id.done).setOnClickListener(this);
-        getDialog().setTitle(R.string.export_flattened);
-
-        updateCompressionFactor();
-        updateSize();
         return view;
     }
 
@@ -148,26 +184,6 @@
         mHandler.postDelayed(mUpdateRunnable, mUpdateDelay);
     }
 
-    @Override
-    public void onClick(View v) {
-        switch (v.getId()) {
-            case R.id.cancel:
-                dismiss();
-                break;
-            case R.id.done:
-                FilterShowActivity activity = (FilterShowActivity) getActivity();
-                Uri sourceUri = MasterImage.getImage().getUri();
-                File dest = SaveImage.getNewFile(activity,  activity.getSelectedImageUri());
-                float scaleFactor = mExportWidth / (float) mOriginalBounds.width();
-                Intent processIntent = ProcessingService.getSaveIntent(activity, MasterImage
-                        .getImage().getPreset(), dest, activity.getSelectedImageUri(), sourceUri,
-                        true, mSeekBar.getProgress(), scaleFactor, false);
-                activity.startService(processIntent);
-                dismiss();
-                break;
-        }
-    }
-
     public void updateCompressionFactor() {
         Bitmap bitmap = MasterImage.getImage().getFilteredImage();
         if (bitmap == null) {
@@ -193,7 +209,7 @@
         compressedSize *= mExportCompressionMargin;
         float size = compressedSize / 1024.f / 1024.f;
         size = ((int) (size * 100)) / 100f;
-        String estimatedSize = "" + size + " Mb";
+        String estimatedSize = "" + size + " MB";
         mEstimatedSize.setText(estimatedSize);
     }
 
@@ -208,7 +224,11 @@
             if (mWidthText.getText() != null) {
                 String value = String.valueOf(mWidthText.getText());
                 if (value.length() > 0) {
-                    width = Integer.parseInt(value);
+                    try {
+                        width = Integer.parseInt(value);
+                    } catch (NumberFormatException e) {
+                        width = Integer.MAX_VALUE;
+                    }
                     if (width > mOriginalBounds.width()) {
                         width = mOriginalBounds.width();
                         mWidthText.setText("" + width);
@@ -225,7 +245,11 @@
             if (mHeightText.getText() != null) {
                 String value = String.valueOf(mHeightText.getText());
                 if (value.length() > 0) {
-                    height = Integer.parseInt(value);
+                    try {
+                        height = Integer.parseInt(value);
+                    } catch (NumberFormatException e) {
+                        height = Integer.MAX_VALUE;
+                    }
                     if (height > mOriginalBounds.height()) {
                         height = mOriginalBounds.height();
                         mHeightText.setText("" + height);
diff --git a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java
index c1e4109..8957f2d 100644
--- a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java
+++ b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java
@@ -25,7 +25,7 @@
 import android.util.AttributeSet;
 import android.widget.ImageButton;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class FramedTextButton extends ImageButton {
     private static final String LOGTAG = "FramedTextButton";
diff --git a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
index 58466bf..0b26e48 100644
--- a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
+++ b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java
@@ -22,20 +22,29 @@
 import android.appwidget.AppWidgetProvider;
 import android.content.Context;
 import android.content.Intent;
+import android.database.ContentObserver;
+import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
+import android.os.Handler;
 import android.util.Log;
+import android.view.View;
 import android.widget.RemoteViews;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry;
 import com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator;
 
+import java.util.ArrayList;
+import java.util.List;
+
 public class PhotoAppWidgetProvider extends AppWidgetProvider {
 
     private static final String TAG = "WidgetProvider";
+    private static List<PhotoUriContentObserver> mPhotoUriObservers = new ArrayList<>();
+    private static Handler mContentObserverHandler = new Handler();
 
     static RemoteViews buildWidget(Context context, int id, Entry entry) {
 
@@ -44,6 +53,12 @@
             case WidgetDatabaseHelper.TYPE_SHUFFLE:
                 return buildStackWidget(context, id, entry);
             case WidgetDatabaseHelper.TYPE_SINGLE_PHOTO:
+                PhotoUriContentObserver photoUriObserver =
+                        new PhotoUriContentObserver(context, mContentObserverHandler, entry, id);
+                photoUriObserver.setTag(id);
+                mPhotoUriObservers.add(photoUriObserver);
+                context.getContentResolver().registerContentObserver(Uri.parse(entry.imageUri),
+                        false, photoUriObserver);
                 return buildFrameWidget(context, id, entry);
         }
         throw new RuntimeException("invalid type - " + entry.type);
@@ -132,8 +147,60 @@
         // Clean deleted photos out of our database
         WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context);
         for (int appWidgetId : appWidgetIds) {
+            PhotoUriContentObserver contentObserver = getContentObserver(appWidgetId);
+            if (contentObserver != null) {
+                context.getContentResolver().unregisterContentObserver(contentObserver);
+                mPhotoUriObservers.remove(contentObserver);
+            }
             helper.deleteEntry(appWidgetId);
         }
         helper.close();
     }
+
+    private PhotoUriContentObserver getContentObserver(int appWidgetId) {
+        for (PhotoUriContentObserver contentObserver : mPhotoUriObservers) {
+            if (appWidgetId == contentObserver.getTag()) {
+                return contentObserver;
+            }
+        }
+        return null;
+    }
+
+    private static class PhotoUriContentObserver extends ContentObserver {
+        private int mId;
+        private int mTag;
+        private Context mContext;
+        private Entry mEntry;
+
+        public void setTag(int tag) {
+            this.mTag = tag;
+        }
+
+        public int getTag() {
+            return mTag;
+        }
+
+        public PhotoUriContentObserver(Context context, Handler handler, Entry entry, int id) {
+            super(handler);
+            mContext = context;
+            mEntry = entry;
+            mId = id;
+        }
+
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            Uri uri = Uri.parse(mEntry.imageUri);
+            Cursor cursor = mContext.getContentResolver().query(uri, null, null,
+                    null, "_id ASC LIMIT 1");
+            if (cursor != null) {
+                if (cursor.getCount() == 0) {
+                    RemoteViews views = buildFrameWidget(mContext, mId, mEntry);
+                    views.setViewVisibility(R.id.appwidget_empty_photo, View.VISIBLE);
+                    views.setViewVisibility(R.id.photo, View.GONE);
+                    AppWidgetManager.getInstance(mContext).updateAppWidget(mId, views);
+                }
+                cursor.close();
+            }
+        }
+    }
 }
diff --git a/src/com/android/gallery3d/gadget/WidgetClickHandler.java b/src/com/android/gallery3d/gadget/WidgetClickHandler.java
index e66a2a6..4a90966 100644
--- a/src/com/android/gallery3d/gadget/WidgetClickHandler.java
+++ b/src/com/android/gallery3d/gadget/WidgetClickHandler.java
@@ -26,7 +26,7 @@
 import android.util.Log;
 import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryActivity;
 import com.android.gallery3d.app.PhotoPage;
 import com.android.gallery3d.common.ApiHelper;
@@ -57,6 +57,8 @@
         Intent intent;
         if (isValidDataUri(uri)) {
             intent = new Intent(Intent.ACTION_VIEW, uri);
+            // Used for checking whether it is from widget
+            intent.putExtra(PhotoPage.KEY_IS_FROM_WIDGET, true);
             if (tediousBack) {
                 intent.putExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, true);
             }
diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java
old mode 100644
new mode 100755
index 2a4c6cf..fd5aa6c
--- a/src/com/android/gallery3d/gadget/WidgetConfigure.java
+++ b/src/com/android/gallery3d/gadget/WidgetConfigure.java
@@ -25,8 +25,9 @@
 import android.os.Bundle;
 import android.util.Log;
 import android.widget.RemoteViews;
+import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AlbumPicker;
 import com.android.gallery3d.app.DialogPicker;
 import com.android.gallery3d.app.GalleryApp;
@@ -148,6 +149,14 @@
         int widgetWidth = Math.round(width * scale);
         int widgetHeight = Math.round(height * scale);
 
+        if (data.getData() != null && data.getData().toString().contains("/video/media")) {
+            Toast.makeText(this, "Please select one picture", Toast.LENGTH_LONG).show();
+            Intent request = new Intent(this, DialogPicker.class)
+                    .setAction(Intent.ACTION_GET_CONTENT)
+                    .setType("image/*");
+            startActivityForResult(request, REQUEST_GET_PHOTO);
+            return;
+        }
         mPickedItem = data.getData();
         Intent request = new Intent(CropActivity.CROP_ACTION, mPickedItem)
                 .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth)
diff --git a/src/com/android/gallery3d/gadget/WidgetService.java b/src/com/android/gallery3d/gadget/WidgetService.java
index fc54fb6..c139aff 100644
--- a/src/com/android/gallery3d/gadget/WidgetService.java
+++ b/src/com/android/gallery3d/gadget/WidgetService.java
@@ -19,12 +19,14 @@
 import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
 import android.content.Intent;
+//import android.drm.DrmHelper;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.view.View;
 import android.widget.RemoteViews;
 import android.widget.RemoteViewsService;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryApp;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.ContentListener;
@@ -116,8 +118,37 @@
 
         @Override
         public RemoteViews getViewAt(int position) {
-            Bitmap bitmap = mSource.getImage(position);
-            if (bitmap == null) return getLoadingView();
+            Bitmap bitmap = null;
+            try {
+                bitmap = mSource.getImage(position);
+            } catch (UnsupportedOperationException e){
+                // catch exception here to avoid FC
+            }
+
+            boolean isDrm = false;
+//            if (DrmHelper.isDrmFile(DrmHelper.getFilePath(
+//                    mApp.getAndroidContext(), mSource.getContentUri(position)))) {
+//                isDrm = true;
+//            }
+
+            if (isDrm) {
+                if (bitmap == null) {
+                    RemoteViews rv = new RemoteViews(mApp.getAndroidContext()
+                            .getPackageName(),
+                            R.layout.appwidget_drm_empty_item);
+                    rv.setOnClickFillInIntent(
+                            R.id.appwidget_photo_item,
+                            new Intent().setFlags(
+                                    Intent.FLAG_ACTIVITY_CLEAR_TOP).setData(
+                                    mSource.getContentUri(position)));
+                    return rv;
+                }
+            } else {
+                if (bitmap == null) {
+                    return getLoadingView();
+                }
+            }
+
             RemoteViews views = new RemoteViews(
                     mApp.getAndroidContext().getPackageName(),
                     R.layout.appwidget_photo_item);
@@ -125,6 +156,13 @@
             views.setOnClickFillInIntent(R.id.appwidget_photo_item, new Intent()
                     .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
                     .setData(mSource.getContentUri(position)));
+
+            if (isDrm) {
+                views.setViewVisibility(R.id.drm_icon, View.VISIBLE);
+            } else {
+                views.setViewVisibility(R.id.drm_icon, View.GONE);
+            }
+
             return views;
         }
 
diff --git a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java b/src/com/android/gallery3d/gadget/WidgetTypeChooser.java
index 1694f1c..177817c 100644
--- a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java
+++ b/src/com/android/gallery3d/gadget/WidgetTypeChooser.java
@@ -25,7 +25,7 @@
 import android.widget.RadioGroup;
 import android.widget.RadioGroup.OnCheckedChangeListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public class WidgetTypeChooser extends Activity {
 
diff --git a/src/com/android/gallery3d/gadget/WidgetUtils.java b/src/com/android/gallery3d/gadget/WidgetUtils.java
index c20c186..8f37ecc 100644
--- a/src/com/android/gallery3d/gadget/WidgetUtils.java
+++ b/src/com/android/gallery3d/gadget/WidgetUtils.java
@@ -24,7 +24,7 @@
 import android.graphics.Paint;
 import android.util.Log;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.util.ThreadPool;
 
diff --git a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java b/src/com/android/gallery3d/glrenderer/GLES11Canvas.java
old mode 100644
new mode 100755
index 74ccfb5..f707c54
--- a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java
+++ b/src/com/android/gallery3d/glrenderer/GLES11Canvas.java
@@ -24,6 +24,7 @@
 import android.opengl.Matrix;
 import android.util.Log;
 
+import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.util.IntArray;
 
@@ -615,7 +616,11 @@
             gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
 
             // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel.
-            gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
+            if (ApiHelper.USE_888_PIXEL_FORMAT) {
+                gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
+            } else {
+                gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
+            }
         }
 
         public void setTexEnvMode(int mode) {
diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
index 4ead131..4c7ae94 100644
--- a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
+++ b/src/com/android/gallery3d/glrenderer/GLES20Canvas.java
@@ -23,6 +23,7 @@
 import android.opengl.Matrix;
 import android.util.Log;
 
+import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.util.IntArray;
 
 import java.nio.Buffer;
@@ -291,6 +292,12 @@
         mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters);
         GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
         checkError();
+
+        if (ApiHelper.USE_888_PIXEL_FORMAT) {
+            GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 2);
+        } else {
+            GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
+        }
     }
 
     private static FloatBuffer createBuffer(float[] values) {
diff --git a/src/com/android/gallery3d/glrenderer/TextureUploader.java b/src/com/android/gallery3d/glrenderer/TextureUploader.java
index f17ab84..bc670ec 100644
--- a/src/com/android/gallery3d/glrenderer/TextureUploader.java
+++ b/src/com/android/gallery3d/glrenderer/TextureUploader.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
+    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested, long dueTime) {
         int uploadQuota = QUOTA_PER_FRAME;
         uploadQuota = upload(canvas, mFgTextures, uploadQuota, false);
         if (uploadQuota < QUOTA_PER_FRAME) mGLRoot.requestRender();
diff --git a/src/com/android/gallery3d/glrenderer/TiledTexture.java b/src/com/android/gallery3d/glrenderer/TiledTexture.java
index 78cb2f2..53a1367 100644
--- a/src/com/android/gallery3d/glrenderer/TiledTexture.java
+++ b/src/com/android/gallery3d/glrenderer/TiledTexture.java
@@ -24,7 +24,6 @@
 import android.graphics.PorterDuff.Mode;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.RectF;
-import android.os.SystemClock;
 
 import com.android.gallery3d.ui.GLRoot;
 import com.android.gallery3d.ui.GLRoot.OnGLIdleListener;
@@ -42,10 +41,6 @@
     private static final int TILE_SIZE = CONTENT_SIZE + 2 * BORDER_SIZE;
     private static final int INIT_CAPACITY = 8;
 
-    // We are targeting at 60fps, so we have 16ms for each frame.
-    // In this 16ms, we use about 4~8 ms to upload tiles.
-    private static final long UPLOAD_TILE_LIMIT = 4; // ms
-
     private static Tile sFreeTileHead = null;
     private static final Object sFreeTileLock = new Object();
 
@@ -64,8 +59,7 @@
     private final RectF mDestRect = new RectF();
 
     public static class Uploader implements OnGLIdleListener {
-        private final ArrayDeque<TiledTexture> mTextures =
-                new ArrayDeque<TiledTexture>(INIT_CAPACITY);
+        private final ArrayDeque<TiledTexture> mTextures = new ArrayDeque<>(INIT_CAPACITY);
 
         private final GLRoot mGlRoot;
         private boolean mIsQueued = false;
@@ -88,18 +82,20 @@
         }
 
         @Override
-        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
+        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested, long dueTime) {
             ArrayDeque<TiledTexture> deque = mTextures;
             synchronized (this) {
-                long now = SystemClock.uptimeMillis();
-                long dueTime = now + UPLOAD_TILE_LIMIT;
-                while (now < dueTime && !deque.isEmpty()) {
+                long now = System.nanoTime();
+                long uploadTime = 0;
+                while (now + uploadTime < dueTime && !deque.isEmpty()) {
                     TiledTexture t = deque.peekFirst();
                     if (t.uploadNextTile(canvas)) {
                         deque.removeFirst();
                         mGlRoot.requestRender();
                     }
-                    now = SystemClock.uptimeMillis();
+                    long t1 = System.nanoTime();
+                    uploadTime = t1 - now;
+                    now = t1;
                 }
                 mIsQueued = !mTextures.isEmpty();
 
@@ -134,13 +130,12 @@
             Bitmap localBitmapRef = bitmap;
             bitmap = null;
 
-            if (localBitmapRef != null) {
+            if (localBitmapRef != null && sCanvas != null) {
                 int x = BORDER_SIZE - offsetX;
                 int y = BORDER_SIZE - offsetY;
                 int r = localBitmapRef.getWidth() + x;
                 int b = localBitmapRef.getHeight() + y;
                 sCanvas.drawBitmap(localBitmapRef, x, y, sBitmapPaint);
-                localBitmapRef = null;
 
                 // draw borders if need
                 if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint);
@@ -202,7 +197,7 @@
     public TiledTexture(Bitmap bitmap) {
         mWidth = bitmap.getWidth();
         mHeight = bitmap.getHeight();
-        ArrayList<Tile> list = new ArrayList<Tile>();
+        ArrayList<Tile> list = new ArrayList<>();
 
         for (int x = 0, w = mWidth; x < w; x += CONTENT_SIZE) {
             for (int y = 0, h = mHeight; y < h; y += CONTENT_SIZE) {
@@ -226,8 +221,8 @@
     // Can be called in UI thread.
     public void recycle() {
         synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                freeTile(mTiles[i]);
+            for (Tile mTile : mTiles) {
+                freeTile(mTile);
             }
         }
     }
@@ -280,8 +275,7 @@
         float scaleX = (float) width / mWidth;
         float scaleY = (float) height / mHeight;
         synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
+            for (Tile t : mTiles) {
                 src.set(0, 0, t.contentWidth, t.contentHeight);
                 src.offset(t.offsetX, t.offsetY);
                 mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
@@ -299,8 +293,7 @@
         float scaleX = (float) width / mWidth;
         float scaleY = (float) height / mHeight;
         synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
+            for (Tile t : mTiles) {
                 src.set(0, 0, t.contentWidth, t.contentHeight);
                 src.offset(t.offsetX, t.offsetY);
                 mapRect(dest, src, 0, 0, x, y, scaleX, scaleY);
@@ -322,8 +315,7 @@
         float scaleY = target.height() / source.height();
 
         synchronized (mTiles) {
-            for (int i = 0, n = mTiles.length; i < n; ++i) {
-                Tile t = mTiles[i];
+            for (Tile t : mTiles) {
                 src.set(0, 0, t.contentWidth, t.contentHeight);
                 src.offset(t.offsetX, t.offsetY);
                 if (!src.intersect(source)) continue;
diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/src/com/android/gallery3d/glrenderer/UploadedTexture.java
index 417102a..fced558 100644
--- a/src/com/android/gallery3d/glrenderer/UploadedTexture.java
+++ b/src/com/android/gallery3d/glrenderer/UploadedTexture.java
@@ -134,6 +134,7 @@
     private Bitmap getBitmap() {
         if (mBitmap == null) {
             mBitmap = onGetBitmap();
+            if (mBitmap == null)return null;
             int w = mBitmap.getWidth() + mBorder * 2;
             int h = mBitmap.getHeight() + mBorder * 2;
             if (mWidth == UNSPECIFIED) {
@@ -188,14 +189,23 @@
             if (mThrottled && ++sUploadedCount > UPLOAD_LIMIT) {
                 return;
             }
-            uploadToCanvas(canvas);
+            try {
+                uploadToCanvas(canvas);
+            } catch (RuntimeException e) {
+                mContentValid = false;
+                e.printStackTrace();
+            }
         } else if (!mContentValid) {
             Bitmap bitmap = getBitmap();
-            int format = GLUtils.getInternalFormat(bitmap);
-            int type = GLUtils.getType(bitmap);
-            canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
-            freeBitmap();
-            mContentValid = true;
+            if (bitmap != null) {
+                int format = GLUtils.getInternalFormat(bitmap);
+                int type = GLUtils.getType(bitmap);
+                canvas.texSubImage2D(this, mBorder, mBorder, bitmap, format, type);
+                freeBitmap();
+                mContentValid = true;
+            } else {
+                mContentValid = false;
+            }
         }
     }
 
@@ -210,7 +220,7 @@
     private void uploadToCanvas(GLCanvas canvas) {
 
         Bitmap bitmap = getBitmap();
-        if (bitmap != null) {
+        if (bitmap != null && !bitmap.isRecycled()) {
             try {
                 int bWidth = bitmap.getWidth();
                 int bHeight = bitmap.getHeight();
@@ -221,8 +231,11 @@
 
                 Utils.assertTrue(bWidth <= texWidth && bHeight <= texHeight);
 
-                // Upload the bitmap to a new texture.
-                mId = canvas.getGLId().generateTexture();
+                // Null pointer check here is to avoid monkey test failure.
+                if (canvas.getGLId() != null) {
+                    // Upload the bitmap to a new texture.
+                    mId = canvas.getGLId().generateTexture();
+                }
                 canvas.setTextureParameters(this);
 
                 if (bWidth == texWidth && bHeight == texHeight) {
@@ -266,7 +279,9 @@
             mContentValid = true;
         } else {
             mState = STATE_ERROR;
-            throw new RuntimeException("Texture load fail, no bitmap");
+            if(bitmap == null) {
+                throw new RuntimeException("Texture load fail, no bitmap");
+            }
         }
     }
 
diff --git a/src/com/android/gallery3d/ingest/IngestActivity.java b/src/com/android/gallery3d/ingest/IngestActivity.java
index b0b3e05..be9f05c 100644
--- a/src/com/android/gallery3d/ingest/IngestActivity.java
+++ b/src/com/android/gallery3d/ingest/IngestActivity.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.adapter.CheckBroker;
 import com.android.gallery3d.ingest.adapter.MtpAdapter;
 import com.android.gallery3d.ingest.adapter.MtpPagerAdapter;
diff --git a/src/com/android/gallery3d/ingest/IngestService.java b/src/com/android/gallery3d/ingest/IngestService.java
index 262e410..3927cd7 100644
--- a/src/com/android/gallery3d/ingest/IngestService.java
+++ b/src/com/android/gallery3d/ingest/IngestService.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.ImportTask;
 import com.android.gallery3d.ingest.data.IngestObjectInfo;
 import com.android.gallery3d.ingest.data.MtpClient;
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
index c3ce59f..766bfef 100644
--- a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
+++ b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.adapter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.IngestObjectInfo;
 import com.android.gallery3d.ingest.data.MtpDeviceIndex;
 import com.android.gallery3d.ingest.data.MtpDeviceIndex.SortOrder;
diff --git a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
index 6c1dd9f..241e595 100644
--- a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
+++ b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.adapter;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.IngestObjectInfo;
 import com.android.gallery3d.ingest.data.MtpDeviceIndex;
 import com.android.gallery3d.ingest.data.MtpDeviceIndex.SortOrder;
diff --git a/src/com/android/gallery3d/ingest/ui/DateTileView.java b/src/com/android/gallery3d/ingest/ui/DateTileView.java
index cd31e82..fc94e6a 100644
--- a/src/com/android/gallery3d/ingest/ui/DateTileView.java
+++ b/src/com/android/gallery3d/ingest/ui/DateTileView.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.ui;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.SimpleDate;
 
 import android.content.Context;
diff --git a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
index 00785dd..b41129d 100644
--- a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
+++ b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.ui;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.adapter.CheckBroker;
 
 import android.content.Context;
diff --git a/src/com/android/gallery3d/ingest/ui/MtpImageView.java b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
index 5362efd..f28d677 100644
--- a/src/com/android/gallery3d/ingest/ui/MtpImageView.java
+++ b/src/com/android/gallery3d/ingest/ui/MtpImageView.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.ui;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.BitmapWithMetadata;
 import com.android.gallery3d.ingest.data.IngestObjectInfo;
 import com.android.gallery3d.ingest.data.MtpBitmapFetch;
diff --git a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
index 844a750..d78e41a 100644
--- a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
+++ b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ingest.ui;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ingest.data.IngestObjectInfo;
 import com.android.gallery3d.ingest.data.MtpBitmapFetch;
 
diff --git a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java b/src/com/android/gallery3d/ui/AbstractSlotRenderer.java
index 729439d..d9a6bc0 100644
--- a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java
+++ b/src/com/android/gallery3d/ui/AbstractSlotRenderer.java
@@ -19,7 +19,8 @@
 import android.content.Context;
 import android.graphics.Rect;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.glrenderer.FadeOutTexture;
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.NinePatchTexture;
@@ -33,14 +34,18 @@
     private final ResourceTexture mPanoramaIcon;
     private final NinePatchTexture mFramePressed;
     private final NinePatchTexture mFrameSelected;
+    private final ResourceTexture mDrmIcon;
+    private final ResourceTexture mSelectionIcon;
     private FadeOutTexture mFramePressedUp;
 
     protected AbstractSlotRenderer(Context context) {
         mVideoOverlay = new ResourceTexture(context, R.drawable.ic_video_thumb);
-        mVideoPlayIcon = new ResourceTexture(context, R.drawable.ic_gallery_play);
+        mVideoPlayIcon = new ResourceTexture(context, R.drawable.play_detail);
         mPanoramaIcon = new ResourceTexture(context, R.drawable.ic_360pano_holo_light);
         mFramePressed = new NinePatchTexture(context, R.drawable.grid_pressed);
         mFrameSelected = new NinePatchTexture(context, R.drawable.grid_selected);
+        mDrmIcon = new ResourceTexture(context, R.drawable.drm_image);
+        mSelectionIcon = new ResourceTexture(context, R.drawable.multiselect);
     }
 
     protected void drawContent(GLCanvas canvas,
@@ -49,7 +54,7 @@
 
         // The content is always rendered in to the largest square that fits
         // inside the slot, aligned to the top of the slot.
-        width = height = Math.min(width, height);
+        //width = height = Math.min(width, height);
         if (rotation != 0) {
             canvas.translate(width / 2, height / 2);
             canvas.rotate(rotation, 0, 0, 1);
@@ -66,21 +71,39 @@
         canvas.restore();
     }
 
-    protected void drawVideoOverlay(GLCanvas canvas, int width, int height) {
+    protected void drawVideoOverlay(GLCanvas canvas, int width, int height,
+            boolean isGridViewShown, int thumbSize) {
         // Scale the video overlay to the height of the thumbnail and put it
         // on the left side.
-        ResourceTexture v = mVideoOverlay;
-        float scale = (float) height / v.getHeight();
-        int w = Math.round(scale * v.getWidth());
-        int h = Math.round(scale * v.getHeight());
-        v.draw(canvas, 0, 0, w, h);
-
-        int s = Math.min(width, height) / 6;
-        mVideoPlayIcon.draw(canvas, (width - s) / 2, (height - s) / 2, s, s);
+        int side = Math.min(width, height) / 6;
+        if (!isGridViewShown)
+            width = thumbSize;
+        mVideoPlayIcon.draw(canvas, width / 8 - side / 2, height * 7 / 8 - side / 2, side, side);
     }
 
-    protected void drawPanoramaIcon(GLCanvas canvas, int width, int height) {
+    protected void drawDrmOverlay(GLCanvas canvas, int width, int height, int Drm_mediaType,
+                boolean isGridViewShown, int thumbSize) {
+        // Scale the video overlay to the height of the thumbnail and put it on the left side.
+        if (Drm_mediaType == MediaObject.MEDIA_TYPE_DRM_VIDEO) {
+            ResourceTexture v = mVideoOverlay;
+            float scale = (float) height / v.getHeight();
+            int w = Math.round(scale * v.getWidth());
+            int h = Math.round(scale * v.getHeight());
+            v.draw(canvas, 0, 0, w, h);
+        }
+        int side = Math.min(width, height) / 6;
+        if (!isGridViewShown) {
+            width = thumbSize;
+        }
+        mDrmIcon.draw(canvas, (width - side) / 2, (height - side) / 2, side, side);
+    }
+
+    protected void drawPanoramaIcon(GLCanvas canvas, int width, int height,
+                   boolean isGridViewShown, int thumbSize) {
         int iconSize = Math.min(width, height) / 6;
+        if (!isGridViewShown) {
+            width = thumbSize;
+        }
         mPanoramaIcon.draw(canvas, (width - iconSize) / 2, (height - iconSize) / 2,
                 iconSize, iconSize);
     }
@@ -108,7 +131,8 @@
     }
 
     protected void drawSelectedFrame(GLCanvas canvas, int width, int height) {
-        drawFrame(canvas, mFrameSelected.getPaddings(), mFrameSelected, 0, 0, width, height);
+        mSelectionIcon.draw(canvas, 5, 5);
+        //drawFrame(canvas, mFrameSelected.getPaddings(), mFrameSelected, 0, 0, width, height);
     }
 
     protected static void drawFrame(GLCanvas canvas, Rect padding, Texture frame,
diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java
index 6b4f103..b78b034 100644
--- a/src/com/android/gallery3d/ui/ActionModeHandler.java
+++ b/src/com/android/gallery3d/ui/ActionModeHandler.java
@@ -18,6 +18,7 @@
 
 import android.annotation.TargetApi;
 import android.app.Activity;
+import android.app.AlertDialog;
 import android.content.Intent;
 import android.net.Uri;
 import android.nfc.NfcAdapter;
@@ -29,16 +30,16 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.Button;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
+import android.widget.Toolbar;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
+import com.android.gallery3d.data.MediaSet;
 import com.android.gallery3d.data.Path;
 import com.android.gallery3d.ui.MenuExecutor.ProgressListener;
 import com.android.gallery3d.util.Future;
@@ -64,6 +65,8 @@
         public boolean onActionItemClicked(MenuItem item);
     }
 
+    public static boolean isThreadComplete = false;
+
     private final AbstractGalleryActivity mActivity;
     private final MenuExecutor mMenuExecutor;
     private final SelectionManager mSelectionManager;
@@ -71,13 +74,15 @@
     private Menu mMenu;
     private MenuItem mSharePanoramaMenuItem;
     private MenuItem mShareMenuItem;
-    private ShareActionProvider mSharePanoramaActionProvider;
-    private ShareActionProvider mShareActionProvider;
     private SelectionMenu mSelectionMenu;
     private ActionModeListener mListener;
     private Future<?> mMenuTask;
     private final Handler mMainHandler;
     private ActionMode mActionMode;
+    private boolean mShareMaxDialog = false;
+    private Toolbar mToolbar;
+    private Intent mShareIntent;
+    private Intent mSharePanoramaIntent;
 
     private static class GetAllPanoramaSupports implements PanoramaSupportCallback {
         private int mNumInfoRequired;
@@ -129,11 +134,14 @@
         mMenuExecutor = new MenuExecutor(activity, selectionManager);
         mMainHandler = new Handler(activity.getMainLooper());
         mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext());
+        mToolbar = mActivity.getToolbar();
     }
 
     public void startActionMode() {
+        mMenuExecutor.setLeaving(false);
         Activity a = mActivity;
-        mActionMode = a.startActionMode(this);
+//      mActionMode = a.startActionMode(this);
+        mActionMode = mActivity.getToolbar().startActionMode(this);
         View customView = LayoutInflater.from(a).inflate(
                 R.layout.action_mode, null);
         mActionMode.setCustomView(customView);
@@ -184,6 +192,12 @@
                             "Gallery Delete Progress Listener");
                 }
                 listener = mDeleteProgressListener;
+            } else if (action == R.id.action_share) {
+                String shareTitle = mActivity.getResources().
+                        getString(R.string.share_dialogue_title);
+                mActivity.startActivity(Intent.createChooser(
+                        mShareIntent, shareTitle));
+                return true;
             }
             mMenuExecutor.onMenuClicked(item, confirmMsg, listener);
         } finally {
@@ -200,6 +214,7 @@
             if (itemId == R.id.action_select_all) {
                 updateSupportedOperation();
                 mMenuExecutor.onMenuClicked(itemId, null, false, true);
+                mSelectionMenu.setLeaving(mMenuExecutor.isLeaving());
             }
             return true;
         } finally {
@@ -213,21 +228,15 @@
         String format = mActivity.getResources().getQuantityString(
                 R.plurals.number_of_items_selected, count);
         setTitle(String.format(format, count));
+        if (count == 0) {
+            mShareMaxDialog = false;
+        }
 
         // For clients who call SelectionManager.selectAll() directly, we need to ensure the
         // menu status is consistent with selection manager.
         mSelectionMenu.updateSelectAllMode(mSelectionManager.inSelectAllMode());
     }
 
-    private final OnShareTargetSelectedListener mShareTargetSelectedListener =
-            new OnShareTargetSelectedListener() {
-        @Override
-        public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
-            mSelectionManager.leaveSelectionMode();
-            return false;
-        }
-    };
-
     @Override
     public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
         return false;
@@ -236,30 +245,34 @@
     @Override
     public boolean onCreateActionMode(ActionMode mode, Menu menu) {
         mode.getMenuInflater().inflate(R.menu.operation, menu);
+        mActivity.getToolbar().setVisibility(View.INVISIBLE);
 
         mMenu = menu;
         mSharePanoramaMenuItem = menu.findItem(R.id.action_share_panorama);
         if (mSharePanoramaMenuItem != null) {
-            mSharePanoramaActionProvider = (ShareActionProvider) mSharePanoramaMenuItem
-                .getActionProvider();
-            mSharePanoramaActionProvider.setOnShareTargetSelectedListener(
-                    mShareTargetSelectedListener);
-            mSharePanoramaActionProvider.setShareHistoryFileName("panorama_share_history.xml");
+            mSharePanoramaMenuItem.setOnMenuItemClickListener(
+                    new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    mSelectionManager.leaveSelectionMode();
+                    if (mSharePanoramaIntent != null) {
+                        Intent intent = Intent.createChooser(mSharePanoramaIntent, null);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mActivity.startActivity(intent);
+                    }
+                    return true;
+                }
+            });
         }
         mShareMenuItem = menu.findItem(R.id.action_share);
-        if (mShareMenuItem != null) {
-            mShareActionProvider = (ShareActionProvider) mShareMenuItem
-                .getActionProvider();
-            mShareActionProvider.setOnShareTargetSelectedListener(
-                    mShareTargetSelectedListener);
-            mShareActionProvider.setShareHistoryFileName("share_history.xml");
-        }
         return true;
     }
 
     @Override
     public void onDestroyActionMode(ActionMode mode) {
         mSelectionManager.leaveSelectionMode();
+        mActivity.getToolbar().setVisibility(View.VISIBLE);
+
     }
 
     private ArrayList<MediaObject> getSelectedMediaObjects(JobContext jc) {
@@ -272,14 +285,17 @@
         ArrayList<MediaObject> selected = new ArrayList<MediaObject>();
         DataManager manager = mActivity.getDataManager();
         for (Path path : unexpandedPaths) {
-            if (jc.isCancelled()) {
+            if (jc.isCancelled() || !mSelectionManager.inSelectionMode()) {
                 return null;
             }
-            selected.add(manager.getMediaObject(path));
+            MediaObject mediaObject = manager.getMediaObject(path);
+            if (mediaObject != null && mediaObject.isSelectable()) {
+                selected.add(mediaObject);
+            }
         }
-
         return selected;
     }
+
     // Menu options are determined by selection set itself.
     // We cannot expand it because MenuExecuter executes it based on
     // the selection set instead of the expanded result.
@@ -301,12 +317,41 @@
                 }
                 break;
             default:
-                operation &= SUPPORT_MULTIPLE_MASK;
+                operation = computeMenuOptionsMultiple(operation, selected.size());
         }
-
         return operation;
     }
 
+    private int computeMenuOptionsMultiple(int operationBefore, int selectedSize) {
+        int operation = operationBefore;
+        if (selectedSize > 1) {
+            operation &= SUPPORT_MULTIPLE_MASK;
+        }
+        return operation;
+    }
+
+    private boolean computeCanShare(ArrayList<MediaObject> selected, int max) {
+        int numSelected = selected.size();
+        boolean ret = computeCanShare(numSelected, max);
+        if (!ret) return false;
+
+        numSelected = 0;
+        for (MediaObject mediaObject : selected) {
+            if (mediaObject instanceof MediaSet) {
+                numSelected = numSelected + ((MediaSet) mediaObject).getTotalMediaItemCount();
+            } else {
+                numSelected = numSelected + 1;
+            }
+            ret = computeCanShare(numSelected, max);
+            if (!ret) return false;
+        }
+        return true;
+    }
+
+    private boolean computeCanShare(int size, int max) {
+        return size <= max;
+    }
+
     @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
     private void setNfcBeamPushUris(Uri[] uris) {
         if (mNfcAdapter != null && ApiHelper.HAS_SET_BEAM_PUSH_URIS) {
@@ -327,7 +372,10 @@
         final Intent intent = new Intent();
         for (Path path : expandedPaths) {
             if (jc.isCancelled()) return null;
-            uris.add(manager.getContentUri(path));
+            Uri uri = manager.getContentUri(path);
+            if (uri != null) {
+                uris.add(uri);
+            }
         }
 
         final int size = uris.size();
@@ -363,7 +411,10 @@
             type |= manager.getMediaType(path);
 
             if ((support & MediaObject.SUPPORT_SHARE) != 0) {
-                uris.add(manager.getContentUri(path));
+                Uri uri = manager.getContentUri(path);
+                if (uri != null) {
+                    uris.add(uri);
+                }
             }
         }
 
@@ -400,12 +451,35 @@
         // Disable share actions until share intent is in good shape
         if (mSharePanoramaMenuItem != null) mSharePanoramaMenuItem.setEnabled(false);
         if (mShareMenuItem != null) mShareMenuItem.setEnabled(false);
+        isThreadComplete = false;
 
         // Generate sharing intent and update supported operations in the background
         // The task can take a long time and be canceled in the mean time.
         mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() {
             @Override
             public Void run(final JobContext jc) {
+                // use selected count to disable menu options and share items if need
+                // to enhance performance.
+                int multipleOperation = SUPPORT_MULTIPLE_MASK;
+                int count = mSelectionManager.getSelectedCount();
+                final int operationPre = computeMenuOptionsMultiple(multipleOperation, count);
+                final boolean canSharePanoramasPre = computeCanShare(count,
+                        MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT);
+                final boolean canSharePre = computeCanShare(count,
+                        MAX_SELECTED_ITEMS_FOR_SHARE_INTENT);
+
+                mMainHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (jc.isCancelled()) return;
+                        MenuExecutor.updateMenuOperation(mMenu, operationPre);
+                        if (mShareMenuItem != null && !canSharePre) {
+                            mShareMenuItem.setEnabled(false);
+                            showShareMaxDialogIfNeed(false);
+                        }
+                    }
+                });
+
                 // Pass1: Deal with unexpanded media object list for menu operation.
                 ArrayList<MediaObject> selected = getSelectedMediaObjects(jc);
                 if (selected == null) {
@@ -424,11 +498,12 @@
                 if (jc.isCancelled()) {
                     return null;
                 }
-                int numSelected = selected.size();
-                final boolean canSharePanoramas =
-                        numSelected < MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT;
-                final boolean canShare =
-                        numSelected < MAX_SELECTED_ITEMS_FOR_SHARE_INTENT;
+
+                // use selected items to compute menu options and share items again.
+                final boolean canShare = canSharePre
+                        && computeCanShare(selected, MAX_SELECTED_ITEMS_FOR_SHARE_INTENT);
+                final boolean canSharePanoramas = canSharePanoramasPre
+                        && computeCanShare(selected, MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT);
 
                 final GetAllPanoramaSupports supportCallback = canSharePanoramas ?
                         new GetAllPanoramaSupports(selected, jc)
@@ -469,11 +544,14 @@
                                 mShareMenuItem.setTitle(
                                     mActivity.getResources().getString(R.string.share));
                             }
-                            mSharePanoramaActionProvider.setShareIntent(share_panorama_intent);
+                            mSharePanoramaIntent = share_panorama_intent;
                         }
                         if (mShareMenuItem != null) {
+                            showShareMaxDialogIfNeed(canShare);
+
                             mShareMenuItem.setEnabled(canShare);
-                            mShareActionProvider.setShareIntent(share_intent);
+                            isThreadComplete = true;
+                            mShareIntent = share_intent;
                         }
                     }
                 });
@@ -482,6 +560,21 @@
         });
     }
 
+    private void showShareMaxDialogIfNeed(boolean canShare) {
+        if (!canShare && !mShareMaxDialog) {
+            AlertDialog.Builder shareMaxDialog = new AlertDialog.Builder(mActivity);
+            shareMaxDialog
+                    .setMessage(R.string.cannot_share_items)
+                    .setPositiveButton(R.string.ok, null)
+                    .create();
+            shareMaxDialog.show();
+            mShareMaxDialog = true;
+        }
+        if (canShare && mShareMaxDialog) {
+            mShareMaxDialog = false;
+        }
+    }
+
     public void pause() {
         if (mMenuTask != null) {
             mMenuTask.cancel();
@@ -495,7 +588,10 @@
     }
 
     public void resume() {
-        if (mSelectionManager.inSelectionMode()) updateSupportedOperation();
+        if (mSelectionManager.inSelectionMode()) {
+            mActivity.getToolbar().setVisibility(View.INVISIBLE);
+            updateSupportedOperation();
+        }
         mMenuExecutor.resume();
     }
 }
diff --git a/src/com/android/gallery3d/ui/AlbumLabelMaker.java b/src/com/android/gallery3d/ui/AlbumLabelMaker.java
index da1cac0..72144ae 100644
--- a/src/com/android/gallery3d/ui/AlbumLabelMaker.java
+++ b/src/com/android/gallery3d/ui/AlbumLabelMaker.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
  * Copyright (C) 2012 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,28 +28,32 @@
 import android.graphics.Typeface;
 import android.text.TextPaint;
 import android.text.TextUtils;
+import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.data.DataSourceType;
 import com.android.photos.data.GalleryBitmapPool;
 import com.android.gallery3d.util.ThreadPool;
 import com.android.gallery3d.util.ThreadPool.JobContext;
 
+import java.util.Locale;
+
 public class AlbumLabelMaker {
     private static final int BORDER_SIZE = 0;
 
-    private final AlbumSetSlotRenderer.LabelSpec mSpec;
-    private final TextPaint mTitlePaint;
-    private final TextPaint mCountPaint;
+    private AlbumSetSlotRenderer.LabelSpec mSpec;
+    private AlbumSlotRenderer.LabelSpec mAlbumListSpec;
+    private TextPaint mTitlePaint;
+    private TextPaint mCountPaint;
     private final Context mContext;
 
     private int mLabelWidth;
     private int mBitmapWidth;
     private int mBitmapHeight;
 
-    private final LazyLoadedBitmap mLocalSetIcon;
+    /*private final LazyLoadedBitmap mLocalSetIcon;
     private final LazyLoadedBitmap mPicasaIcon;
-    private final LazyLoadedBitmap mCameraIcon;
+    private final LazyLoadedBitmap mCameraIcon;*/
 
     public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) {
         mContext = context;
@@ -54,16 +61,22 @@
         mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false);
         mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false);
 
-        mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder);
+        /*mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder);
         mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa);
-        mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera);
+        mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera);*/
+    }
+
+    public AlbumLabelMaker(Context context, AlbumSlotRenderer.LabelSpec spec) {
+        mContext = context;
+        mAlbumListSpec = spec;
+        mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false);
     }
 
     public static int getBorderSize() {
         return BORDER_SIZE;
     }
 
-    private Bitmap getOverlayAlbumIcon(int sourceType) {
+    /*private Bitmap getOverlayAlbumIcon(int sourceType) {
         switch (sourceType) {
             case DataSourceType.TYPE_CAMERA:
                 return mCameraIcon.get();
@@ -73,13 +86,14 @@
                 return mPicasaIcon.get();
         }
         return null;
-    }
+    }*/
 
     private static TextPaint getTextPaint(int textSize, int color, boolean isBold) {
         TextPaint paint = new TextPaint();
         paint.setTextSize(textSize);
         paint.setAntiAlias(true);
         paint.setColor(color);
+        paint.setTypeface(Typeface.SANS_SERIF);
         //paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY);
         if (isBold) {
             paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
@@ -106,12 +120,16 @@
         }
     }
 
-    public synchronized void setLabelWidth(int width) {
+    public synchronized void setLabelWidth(int width, String key) {
         if (mLabelWidth == width) return;
         mLabelWidth = width;
         int borders = 2 * BORDER_SIZE;
         mBitmapWidth = width + borders;
-        mBitmapHeight = mSpec.labelBackgroundHeight + borders;
+        if (key.equalsIgnoreCase(AlbumSetSlidingWindow.KEY_ALBUM)) {
+            mBitmapHeight = mSpec.labelBackgroundHeight + borders;
+        } else {
+            mBitmapHeight = mAlbumListSpec.labelBackgroundHeight + borders;
+        }
     }
 
     public ThreadPool.Job<Bitmap> requestLabel(
@@ -119,6 +137,10 @@
         return new AlbumLabelJob(title, count, sourceType);
     }
 
+    public ThreadPool.Job<Bitmap> requestLabel(String title) {
+        return new AlbumLabelJob(title);
+    }
+
     static void drawText(Canvas canvas,
             int x, int y, String text, int lengthLimit, TextPaint p) {
         // The TextPaint cannot be used concurrently
@@ -131,8 +153,9 @@
 
     private class AlbumLabelJob implements ThreadPool.Job<Bitmap> {
         private final String mTitle;
-        private final String mCount;
-        private final int mSourceType;
+        private String mCount;
+        private int mSourceType;
+        private boolean isAlbumListViewShown;
 
         public AlbumLabelJob(String title, String count, int sourceType) {
             mTitle = title;
@@ -140,13 +163,20 @@
             mSourceType = sourceType;
         }
 
+        public AlbumLabelJob(String title) {
+            mTitle = title;
+            isAlbumListViewShown = true;
+
+        }
+
         @Override
         public Bitmap run(JobContext jc) {
             AlbumSetSlotRenderer.LabelSpec s = mSpec;
+            AlbumSlotRenderer.LabelSpec s1 = mAlbumListSpec;
 
             String title = mTitle;
             String count = mCount;
-            Bitmap icon = getOverlayAlbumIcon(mSourceType);
+            //Bitmap icon = getOverlayAlbumIcon(mSourceType);
 
             Bitmap bitmap;
             int labelWidth;
@@ -156,46 +186,87 @@
                 bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth, mBitmapHeight);
             }
 
-            if (bitmap == null) {
-                int borders = 2 * BORDER_SIZE;
+            int borders = 2 * BORDER_SIZE;
+            if (!isAlbumListViewShown) {
+                if (bitmap == null) {
+
+                    bitmap = Bitmap
+                            .createBitmap(labelWidth + borders,
+                                    s.labelBackgroundHeight + borders,
+                                    Config.ARGB_8888);
+                }
+            } else {
                 bitmap = Bitmap.createBitmap(labelWidth + borders,
-                        s.labelBackgroundHeight + borders, Config.ARGB_8888);
+                        s1.labelBackgroundHeight + borders, Config.ARGB_8888);
             }
 
             Canvas canvas = new Canvas(bitmap);
             canvas.clipRect(BORDER_SIZE, BORDER_SIZE,
                     bitmap.getWidth() - BORDER_SIZE,
                     bitmap.getHeight() - BORDER_SIZE);
-            canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
+            if (!isAlbumListViewShown) {
+                 canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC);
+            }
 
             canvas.translate(BORDER_SIZE, BORDER_SIZE);
 
-            // draw title
-            if (jc.isCancelled()) return null;
-            int x = s.leftMargin + s.iconSize;
-            // TODO: is the offset relevant in new reskin?
-            // int y = s.titleOffset;
-            int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
-            drawText(canvas, x, y, title, labelWidth - s.leftMargin - x - 
-                    s.titleRightMargin, mTitlePaint);
-
-            // draw count
-            if (jc.isCancelled()) return null;
-            x = labelWidth - s.titleRightMargin;
-            y = (s.labelBackgroundHeight - s.countFontSize) / 2;
-            drawText(canvas, x, y, count,
-                    labelWidth - x , mCountPaint);
-
-            // draw the icon
-            if (icon != null) {
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())) {// RTL
+                // draw title
                 if (jc.isCancelled()) return null;
-                float scale = (float) s.iconSize / icon.getWidth();
-                canvas.translate(s.leftMargin, (s.labelBackgroundHeight -
-                        Math.round(scale * icon.getHeight()))/2f);
-                canvas.scale(scale, scale);
-                canvas.drawBitmap(icon, 0, 0, null);
-            }
+                int strLength = (int) mTitlePaint.measureText(title);
+                if (!isAlbumListViewShown) {
+                    int x = labelWidth - s.leftMargin - strLength;
+                    // TODO: is the offset relevant in new reskin?
+                    // int y = s.titleOffset;
+                    int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
+                    drawText(canvas, x, y, title, labelWidth - s.leftMargin - x, mTitlePaint);
 
+                    // draw count
+                    if (jc.isCancelled()) return null;
+                    x = s.leftMargin + 10;// plus 10 to get a much bigger margin
+                    y = (s.labelBackgroundHeight - s.countFontSize) / 2;
+                    drawText(canvas, x, y, count, labelWidth - x, mCountPaint);
+                } else {
+                    int x = labelWidth
+                            - (s1.leftMargin + s1.iconSize)
+                            - strLength;
+                    // TODO: is the offset relevant in new reskin?
+                    // int y = s.titleOffset;
+                    int y = (s1.labelBackgroundHeight - s1.titleFontSize) / 2;
+                    drawText(canvas, x, y, title, labelWidth - s1.leftMargin
+                            - x, mTitlePaint);
+                }
+
+            } else { // LTR
+                                // draw title
+                if (jc.isCancelled())
+                    return null;
+                if (!isAlbumListViewShown) {
+                    int x = s.leftMargin + s.titleLeftMargin;
+                    // TODO: is the offset relevant in new reskin?
+                    // int y = s.titleOffset;
+                    int y = (s.labelBackgroundHeight - s.titleFontSize) / 2;
+                    drawText(canvas, x, y, title, labelWidth - s.leftMargin - x
+                            - s.titleRightMargin - s.countRightMargin, mTitlePaint);
+
+                    // draw count
+                    if (jc.isCancelled())
+                        return null;
+                    x = labelWidth - s.titleRightMargin - s.countRightMargin;
+                    y = (s.labelBackgroundHeight - s.countFontSize) / 2;
+                    drawText(canvas, x, y, count, labelWidth - x, mCountPaint);
+                } else {
+
+                    int x = s1.leftMargin + s1.iconSize;
+                    // TODO: is the offset relevant in new reskin?
+                    // int y = s.titleOffset;
+                    int y = (s1.labelBackgroundHeight - s1.titleFontSize) / 2;
+
+                    drawText(canvas, x, y, title, labelWidth - s1.leftMargin
+                            - x, mTitlePaint);
+                }
+          }
             return bitmap;
         }
     }
diff --git a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
index 8149df4..4f462b4 100644
--- a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java
@@ -19,7 +19,7 @@
 import android.graphics.Bitmap;
 import android.os.Message;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.app.AlbumSetDataLoader;
 import com.android.gallery3d.common.Utils;
@@ -39,6 +39,7 @@
 public class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener {
     private static final String TAG = "AlbumSetSlidingWindow";
     private static final int MSG_UPDATE_ALBUM_ENTRY = 1;
+    public static final String KEY_ALBUM = "AlbumSet";
 
     public static interface Listener {
         public void onSizeChanged(int size);
@@ -527,7 +528,7 @@
 
         mSlotWidth = width;
         mLoadingLabel = null;
-        mLabelMaker.setLabelWidth(mSlotWidth);
+        mLabelMaker.setLabelWidth(mSlotWidth,KEY_ALBUM);
 
         if (!mIsActive) return;
 
diff --git a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java
index 5332ef8..264325a 100644
--- a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java
+++ b/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java
@@ -16,7 +16,7 @@
 
 package com.android.gallery3d.ui;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.app.AlbumSetDataLoader;
 import com.android.gallery3d.data.MediaObject;
@@ -58,11 +58,13 @@
         public int countFontSize;
         public int leftMargin;
         public int iconSize;
+        public int titleLeftMargin;
         public int titleRightMargin;
         public int backgroundColor;
         public int titleColor;
         public int countColor;
         public int borderSize;
+        public int countRightMargin;
     }
 
     public AlbumSetSlotRenderer(AbstractGalleryActivity activity,
@@ -183,7 +185,6 @@
                 ((FadeInTexture) content).isAnimating()) {
             renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
         }
-
         return renderRequestFlags;
     }
 
diff --git a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
index fec7d1e..f0540b1 100644
--- a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
+++ b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
  * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,17 +19,28 @@
 
 package com.android.gallery3d.ui;
 
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Bitmap.Config;
 import android.os.Message;
+import android.text.TextPaint;
+import android.text.TextUtils;
 
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.app.AlbumDataLoader;
+import com.android.gallery3d.app.AlbumPage;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback;
 import com.android.gallery3d.data.Path;
+import com.android.gallery3d.glrenderer.BitmapTexture;
 import com.android.gallery3d.glrenderer.Texture;
+import com.android.gallery3d.glrenderer.TextureUploader;
 import com.android.gallery3d.glrenderer.TiledTexture;
 import com.android.gallery3d.util.Future;
 import com.android.gallery3d.util.FutureListener;
@@ -38,14 +52,18 @@
 
     private static final int MSG_UPDATE_ENTRY = 0;
     private static final int JOB_LIMIT = 2;
+    private static final int MSG_UPDATE_ALBUM_ENTRY = 1;
+    public static final String KEY_ALBUM = "Album";
 
     public static interface Listener {
         public void onSizeChanged(int size);
+
         public void onContentChanged();
     }
 
     public static class AlbumEntry {
         public MediaItem item;
+        public String name; // For title of image
         public Path path;
         public boolean isPanorama;
         public int rotation;
@@ -55,6 +73,9 @@
         public Texture content;
         private BitmapLoader contentLoader;
         private PanoSupportListener mPanoSupportListener;
+        public BitmapTexture labelTexture;
+        private BitmapLoader labelLoader;
+
     }
 
     private final AlbumDataLoader mSource;
@@ -75,36 +96,64 @@
 
     private int mActiveRequestCount = 0;
     private boolean mIsActive = false;
+    private AlbumLabelMaker mLabelMaker;
+    private int mSlotWidth;
+    private BitmapTexture mLoadingLabel;
+    private TextureUploader mLabelUploader;
+    private int mCurrentView;
+    private AbstractGalleryActivity mActivity;
+    private boolean isSlotSizeChanged;
+    private boolean mViewType;
 
     private class PanoSupportListener implements PanoramaSupportCallback {
         public final AlbumEntry mEntry;
-        public PanoSupportListener (AlbumEntry entry) {
+
+        public PanoSupportListener(AlbumEntry entry) {
             mEntry = entry;
         }
+
         @Override
-        public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama,
-                boolean isPanorama360) {
-            if (mEntry != null) mEntry.isPanorama = isPanorama;
+        public void panoramaInfoAvailable(MediaObject mediaObject,
+                boolean isPanorama, boolean isPanorama360) {
+            if (mEntry != null)
+                mEntry.isPanorama = isPanorama;
         }
     }
 
     public AlbumSlidingWindow(AbstractGalleryActivity activity,
-            AlbumDataLoader source, int cacheSize) {
+            AlbumDataLoader source, int cacheSize,
+            AlbumSlotRenderer.LabelSpec labelSpec, boolean viewType) {
         source.setDataListener(this);
         mSource = source;
+        mViewType = viewType;
         mData = new AlbumEntry[cacheSize];
         mSize = source.size();
-
         mHandler = new SynchronizedHandler(activity.getGLRoot()) {
             @Override
             public void handleMessage(Message message) {
-                Utils.assertTrue(message.what == MSG_UPDATE_ENTRY);
-                ((ThumbnailLoader) message.obj).updateEntry();
+                switch (message.what) {
+                case 0:
+                    Utils.assertTrue(message.what == MSG_UPDATE_ENTRY);
+                    ((ThumbnailLoader) message.obj).updateEntry();
+                    break;
+                case 1:
+                    Utils.assertTrue(message.what == MSG_UPDATE_ALBUM_ENTRY);
+                    ((EntryUpdater) message.obj).updateEntry();
+                    break;
+                }
+
             }
         };
 
         mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT);
+        if (!mViewType) {
+            mLabelMaker = new AlbumLabelMaker(activity.getAndroidContext(),
+                    labelSpec);
+            mLabelUploader = new TextureUploader(activity.getGLRoot());
+        }
         mTileUploader = new TiledTexture.Uploader(activity.getGLRoot());
+        mActivity = activity;
+
     }
 
     public void setListener(Listener listener) {
@@ -113,8 +162,8 @@
 
     public AlbumEntry get(int slotIndex) {
         if (!isActiveSlot(slotIndex)) {
-            Utils.fail("invalid slot: %s outsides (%s, %s)",
-                    slotIndex, mActiveStart, mActiveEnd);
+            Utils.fail("invalid slot: %s outsides (%s, %s)", slotIndex,
+                    mActiveStart, mActiveEnd);
         }
         return mData[slotIndex % mData.length];
     }
@@ -124,7 +173,8 @@
     }
 
     private void setContentWindow(int contentStart, int contentEnd) {
-        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
+        if (contentStart == mContentStart && contentEnd == mContentEnd)
+            return;
 
         if (!mIsActive) {
             mContentStart = contentStart;
@@ -170,12 +220,13 @@
         mActiveStart = start;
         mActiveEnd = end;
 
-        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
-                0, Math.max(0, mSize - data.length));
+        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2, 0,
+                Math.max(0, mSize - data.length));
         int contentEnd = Math.min(contentStart + data.length, mSize);
         setContentWindow(contentStart, contentEnd);
         updateTextureUploadQueue();
-        if (mIsActive) updateAllImageRequests();
+        if (mIsActive)
+            updateAllImageRequests();
     }
 
     private void uploadBgTextureInSlot(int index) {
@@ -184,12 +235,21 @@
             if (entry.bitmapTexture != null) {
                 mTileUploader.addTexture(entry.bitmapTexture);
             }
+            if (!mViewType) {
+                if (entry.labelTexture != null) {
+                    mLabelUploader.addBgTexture(entry.labelTexture);
+                }
+            }
         }
     }
 
     private void updateTextureUploadQueue() {
-        if (!mIsActive) return;
+        if (!mIsActive)
+            return;
         mTileUploader.clear();
+        if (!mViewType) {
+            mLabelUploader.clear();
+        }
 
         // add foreground textures
         for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
@@ -197,11 +257,16 @@
             if (entry.bitmapTexture != null) {
                 mTileUploader.addTexture(entry.bitmapTexture);
             }
+            if (!mViewType) {
+                if (entry.labelTexture != null) {
+                    mLabelUploader.addFgTexture(entry.labelTexture);
+                }
+            }
         }
 
         // add background textures
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
+        int range = Math.max((mContentEnd - mActiveEnd),
+                (mActiveStart - mContentStart));
         for (int i = 0; i < range; ++i) {
             uploadBgTextureInSlot(mActiveEnd + i);
             uploadBgTextureInSlot(mActiveStart - i - 1);
@@ -209,54 +274,108 @@
     }
 
     // We would like to request non active slots in the following order:
-    // Order:    8 6 4 2                   1 3 5 7
-    //         |---------|---------------|---------|
-    //                   |<-  active  ->|
-    //         |<-------- cached range ----------->|
+    // Order: 8 6 4 2 1 3 5 7
+    // |---------|---------------|---------|
+    // |<- active ->|
+    // |<-------- cached range ----------->|
     private void requestNonactiveImages() {
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0 ;i < range; ++i) {
-            requestSlotImage(mActiveEnd + i);
-            requestSlotImage(mActiveStart - 1 - i);
+        int range = Math.max((mContentEnd - mActiveEnd),
+                (mActiveStart - mContentStart));
+        for (int i = 0; i < range; ++i) {
+            // requestSlotImage(mActiveEnd + i);
+            // requestSlotImage(mActiveStart - 1 - i);
+            requestImagesInSlot(mActiveEnd + i);
+            requestImagesInSlot(mActiveStart - 1 - i);
         }
+        isSlotSizeChanged = false;
+    }
+
+    private void requestImagesInSlot(int slotIndex) {
+        if (slotIndex < mContentStart || slotIndex >= mContentEnd)
+            return;
+        AlbumEntry entry = mData[slotIndex % mData.length];
+        if (isSlotSizeChanged && !mViewType) {
+            if ((entry.content != null || entry.item == null)
+                    && entry.labelTexture != null) {
+                return;
+
+            } else {
+                if (entry.labelLoader != null)
+                    entry.labelLoader.startLoad();
+            }
+        } else {
+            if (entry.content != null || entry.item == null)
+                return;
+            entry.mPanoSupportListener = new PanoSupportListener(entry);
+            entry.item.getPanoramaSupport(entry.mPanoSupportListener);
+            if (entry.contentLoader != null)
+                entry.contentLoader.startLoad();
+            if (!mViewType) {
+
+                if (entry.labelLoader != null)
+                    entry.labelLoader.startLoad();
+            }
+        }
+
     }
 
     // return whether the request is in progress or not
     private boolean requestSlotImage(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false;
+        if (slotIndex < mContentStart || slotIndex >= mContentEnd)
+            return false;
         AlbumEntry entry = mData[slotIndex % mData.length];
-        if (entry.content != null || entry.item == null) return false;
+        if (entry.content != null || entry.item == null)
+            return false;
 
         // Set up the panorama callback
         entry.mPanoSupportListener = new PanoSupportListener(entry);
         entry.item.getPanoramaSupport(entry.mPanoSupportListener);
 
-        entry.contentLoader.startLoad();
         return entry.contentLoader.isRequestInProgress();
     }
 
+    private static boolean startLoadBitmap(BitmapLoader loader) {
+        if (loader == null)
+            return false;
+        loader.startLoad();
+        return loader.isRequestInProgress();
+    }
+
     private void cancelNonactiveImages() {
-        int range = Math.max(
-                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
-        for (int i = 0 ;i < range; ++i) {
+        int range = Math.max((mContentEnd - mActiveEnd),
+                (mActiveStart - mContentStart));
+        for (int i = 0; i < range; ++i) {
             cancelSlotImage(mActiveEnd + i);
             cancelSlotImage(mActiveStart - 1 - i);
         }
     }
 
     private void cancelSlotImage(int slotIndex) {
-        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
+        if (slotIndex < mContentStart || slotIndex >= mContentEnd)
+            return;
         AlbumEntry item = mData[slotIndex % mData.length];
-        if (item.contentLoader != null) item.contentLoader.cancelLoad();
+        if (item.contentLoader != null)
+            item.contentLoader.cancelLoad();
+        if (!mViewType) {
+            if (item.labelLoader != null)
+                item.labelLoader.cancelLoad();
+        }
     }
 
     private void freeSlotContent(int slotIndex) {
         AlbumEntry data[] = mData;
         int index = slotIndex % data.length;
         AlbumEntry entry = data[index];
-        if (entry.contentLoader != null) entry.contentLoader.recycle();
-        if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
+        if (entry.contentLoader != null)
+            entry.contentLoader.recycle();
+        if (!mViewType) {
+            if (entry.labelLoader != null)
+                entry.labelLoader.recycle();
+            if (entry.labelTexture != null)
+                entry.labelTexture.recycle();
+        }
+        if (entry.bitmapTexture != null)
+            entry.bitmapTexture.recycle();
         data[index] = null;
     }
 
@@ -264,28 +383,63 @@
         AlbumEntry entry = new AlbumEntry();
         MediaItem item = mSource.get(slotIndex); // item could be null;
         entry.item = item;
-        entry.mediaType = (item == null)
-                ? MediaItem.MEDIA_TYPE_UNKNOWN
+        entry.name = (item == null) ? null : item.getName();
+        entry.mediaType = (item == null) ? MediaItem.MEDIA_TYPE_UNKNOWN
                 : entry.item.getMediaType();
         entry.path = (item == null) ? null : item.getPath();
         entry.rotation = (item == null) ? 0 : item.getRotation();
         entry.contentLoader = new ThumbnailLoader(slotIndex, entry.item);
+        if (!mViewType) {
+            if (entry.labelLoader != null) {
+                entry.labelLoader.recycle();
+                entry.labelLoader = null;
+                entry.labelTexture = null;
+            }
+            if (entry.name != null) {
+                entry.labelLoader = new AlbumLabelLoader(slotIndex, entry.name);
+            }
+        }
         mData[slotIndex % mData.length] = entry;
     }
 
     private void updateAllImageRequests() {
         mActiveRequestCount = 0;
         for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
-            if (requestSlotImage(i)) ++mActiveRequestCount;
+            AlbumEntry entry = mData[i % mData.length];
+            if (isSlotSizeChanged) {
+                if ((entry.content != null || entry.item == null)
+                        && entry.labelTexture != null) {
+                    continue;
+                } else {
+                    if (startLoadBitmap(entry.labelLoader))
+                        ++mActiveRequestCount;
+                }
+
+            }
+
+            else {
+                if (entry.content != null || entry.item == null)
+                    continue;
+                if (startLoadBitmap(entry.contentLoader))
+                    ++mActiveRequestCount;
+                if (!mViewType) {
+                    if (startLoadBitmap(entry.labelLoader))
+                        ++mActiveRequestCount;
+                }
+            }
+
+            // if (requestSlotImage(i)) ++mActiveRequestCount;
         }
-        if (mActiveRequestCount == 0) {
+
+        if (isSlotSizeChanged || mActiveRequestCount == 0) {
             requestNonactiveImages();
         } else {
+
             cancelNonactiveImages();
         }
     }
 
-    private class ThumbnailLoader extends BitmapLoader  {
+    private class ThumbnailLoader extends BitmapLoader {
         private final int mSlotIndex;
         private final MediaItem mItem;
 
@@ -307,7 +461,9 @@
 
         public void updateEntry() {
             Bitmap bitmap = getBitmap();
-            if (bitmap == null) return; // error or recycled
+
+            if (bitmap == null)
+                return; // error or recycled
             AlbumEntry entry = mData[mSlotIndex % mData.length];
             entry.bitmapTexture = new TiledTexture(bitmap);
             entry.content = entry.bitmapTexture;
@@ -315,8 +471,10 @@
             if (isActiveSlot(mSlotIndex)) {
                 mTileUploader.addTexture(entry.bitmapTexture);
                 --mActiveRequestCount;
-                if (mActiveRequestCount == 0) requestNonactiveImages();
-                if (mListener != null) mListener.onContentChanged();
+                if (mActiveRequestCount == 0)
+                    requestNonactiveImages();
+                if (mListener != null)
+                    mListener.onContentChanged();
             } else {
                 mTileUploader.addTexture(entry.bitmapTexture);
             }
@@ -327,9 +485,12 @@
     public void onSizeChanged(int size) {
         if (mSize != size) {
             mSize = size;
-            if (mListener != null) mListener.onSizeChanged(mSize);
-            if (mContentEnd > mSize) mContentEnd = mSize;
-            if (mActiveEnd > mSize) mActiveEnd = mSize;
+            if (mListener != null)
+                mListener.onSizeChanged(mSize);
+            if (mContentEnd > mSize)
+                mContentEnd = mSize;
+            if (mActiveEnd > mSize)
+                mActiveEnd = mSize;
         }
     }
 
@@ -356,10 +517,88 @@
 
     public void pause() {
         mIsActive = false;
+        if (!mViewType)
+            mLabelUploader.clear();
         mTileUploader.clear();
         TiledTexture.freeResources();
         for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
             freeSlotContent(i);
         }
     }
+
+    private static interface EntryUpdater {
+        public void updateEntry();
+    }
+
+    private class AlbumLabelLoader extends BitmapLoader implements EntryUpdater {
+        private final int mSlotIndex;
+        private final String mTitle;
+
+        public AlbumLabelLoader(int slotIndex, String title) {
+            mSlotIndex = slotIndex;
+            mTitle = title;
+            // mTotalCount = totalCount;
+            // mSourceType = sourceType;
+        }
+
+        @Override
+        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
+            return mThreadPool.submit(mLabelMaker.requestLabel(mTitle), this);
+        }
+
+        @Override
+        protected void onLoadComplete(Bitmap bitmap) {
+            mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget();
+        }
+
+        @Override
+        public void updateEntry() {
+            Bitmap bitmap = getBitmap();
+            if (bitmap == null)
+                return; // Error or recycled
+
+            AlbumEntry entry = mData[mSlotIndex % mData.length];
+            entry.labelTexture = new BitmapTexture(bitmap);
+            entry.labelTexture.setOpaque(false);
+            // entry.labelTexture = texture;
+
+            if (isActiveSlot(mSlotIndex)) {
+                mLabelUploader.addFgTexture(entry.labelTexture);
+                --mActiveRequestCount;
+                if (mActiveRequestCount == 0)
+                    requestNonactiveImages();
+                if (mListener != null)
+                    mListener.onContentChanged();
+            } else {
+                mLabelUploader.addBgTexture(entry.labelTexture);
+            }
+        }
+    }
+
+    public void onSlotSizeChanged(int width, int height) {
+        if (mSlotWidth == width)
+            return;
+
+        isSlotSizeChanged = !mViewType ;
+        mSlotWidth = width;
+        mLoadingLabel = null;
+        mLabelMaker.setLabelWidth(mSlotWidth,KEY_ALBUM);
+
+        if (!mIsActive)
+            return;
+
+        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
+            AlbumEntry entry = mData[i % mData.length];
+            if (entry.labelLoader != null) {
+                entry.labelLoader.recycle();
+                entry.labelLoader = null;
+                entry.labelTexture = null;
+            }
+            if (entry.name != null) {
+                entry.labelLoader = new AlbumLabelLoader(i, entry.name);
+            }
+        }
+        updateAllImageRequests();
+        updateTextureUploadQueue();
+    }
 }
diff --git a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSlotRenderer.java
index dc6c89b..a4096dc 100644
--- a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java
+++ b/src/com/android/gallery3d/ui/AlbumSlotRenderer.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
  * Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +21,7 @@
 
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.app.AlbumDataLoader;
+import com.android.gallery3d.app.AlbumPage;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.Path;
 import com.android.gallery3d.glrenderer.ColorTexture;
@@ -25,10 +29,24 @@
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.Texture;
 import com.android.gallery3d.glrenderer.TiledTexture;
+import com.android.gallery3d.glrenderer.UploadedTexture;
+import com.android.gallery3d.ui.AlbumSlidingWindow.AlbumEntry;
 
 public class AlbumSlotRenderer extends AbstractSlotRenderer {
     @SuppressWarnings("unused")
     private static final String TAG = "AlbumView";
+    private boolean mIsGridViewShown;
+
+    public static class LabelSpec {
+        public int labelBackgroundHeight;
+        public int titleFontSize;
+        public int leftMargin;
+        public int iconSize;
+        public int titleLeftMargin;
+        public int backgroundColor;
+        public int titleColor;
+        public int borderSize;
+    }
 
     public interface SlotFilter {
         public boolean acceptSlot(int index);
@@ -40,7 +58,7 @@
     private AlbumSlidingWindow mDataWindow;
     private final AbstractGalleryActivity mActivity;
     private final ColorTexture mWaitLoadingTexture;
-    private final SlotView mSlotView;
+    private SlotView mSlotView;
     private final SelectionManager mSelectionManager;
 
     private int mPressedIndex = -1;
@@ -49,33 +67,40 @@
     private boolean mInSelectionMode;
 
     private SlotFilter mSlotFilter;
+    protected final LabelSpec mLabelSpec;
 
-    public AlbumSlotRenderer(AbstractGalleryActivity activity, SlotView slotView,
-            SelectionManager selectionManager, int placeholderColor) {
+    public AlbumSlotRenderer(AbstractGalleryActivity activity,
+            SlotView slotView, LabelSpec labelSpec,
+            SelectionManager selectionManager, int placeholderColor,
+            boolean viewType) {
         super(activity);
         mActivity = activity;
         mSlotView = slotView;
         mSelectionManager = selectionManager;
         mPlaceholderColor = placeholderColor;
-
+        mLabelSpec = labelSpec;
         mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
         mWaitLoadingTexture.setSize(1, 1);
+        mIsGridViewShown = viewType;
     }
 
     public void setPressedIndex(int index) {
-        if (mPressedIndex == index) return;
+        if (mPressedIndex == index)
+            return;
         mPressedIndex = index;
         mSlotView.invalidate();
     }
 
     public void setPressedUp() {
-        if (mPressedIndex == -1) return;
+        if (mPressedIndex == -1)
+            return;
         mAnimatePressedUp = true;
         mSlotView.invalidate();
     }
 
     public void setHighlightItemPath(Path path) {
-        if (mHighlightItemPath == path) return;
+        if (mHighlightItemPath == path)
+            return;
         mHighlightItemPath = path;
         mSlotView.invalidate();
     }
@@ -87,22 +112,28 @@
             mDataWindow = null;
         }
         if (model != null) {
-            mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE);
+            mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE,
+                    mLabelSpec, mIsGridViewShown);
             mDataWindow.setListener(new MyDataModelListener());
             mSlotView.setSlotCount(model.size());
+
         }
     }
 
     private static Texture checkTexture(Texture texture) {
         return (texture instanceof TiledTexture)
-                && !((TiledTexture) texture).isReady()
-                ? null
-                : texture;
+                && !((TiledTexture) texture).isReady() ? null : texture;
     }
 
     @Override
-    public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
-        if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0;
+    public int renderSlot(GLCanvas canvas, int index, int pass, int width,
+            int height) {
+        int thumbSize = 0;
+        if (!mIsGridViewShown) {
+            thumbSize = mLabelSpec.iconSize;
+        }
+        if (mSlotFilter != null && !mSlotFilter.acceptSlot(index))
+            return 0;
 
         AlbumSlidingWindow.AlbumEntry entry = mDataWindow.get(index);
 
@@ -117,18 +148,33 @@
             content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
             entry.content = content;
         }
-        drawContent(canvas, content, width, height, entry.rotation);
-        if ((content instanceof FadeInTexture) &&
-                ((FadeInTexture) content).isAnimating()) {
+        if (mIsGridViewShown) {
+            drawContent(canvas, content, width, height, entry.rotation);
+        } else {
+            // In List View, the content is always rendered in to the largest square that fits
+            // inside the slot, aligned to the top of the slot.
+            int minSize = Math.min(width, height);
+            drawContent(canvas, content, minSize, minSize, entry.rotation);
+        }
+        if ((content instanceof FadeInTexture)
+                && ((FadeInTexture) content).isAnimating()) {
             renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
         }
+        if (!mIsGridViewShown)
+            renderRequestFlags |= renderLabel(canvas, entry, width, height);
 
         if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
-            drawVideoOverlay(canvas, width, height);
+            drawVideoOverlay(canvas, width, height, mIsGridViewShown, thumbSize);
+        }
+
+        if ((entry.mediaType == MediaObject.MEDIA_TYPE_DRM_VIDEO)
+                || (entry.mediaType == MediaObject.MEDIA_TYPE_DRM_IMAGE)) {
+            drawDrmOverlay(canvas, width, height, entry.mediaType,
+                    mIsGridViewShown, thumbSize);
         }
 
         if (entry.isPanorama) {
-            drawPanoramaIcon(canvas, width, height);
+            drawPanoramaIcon(canvas, width, height, mIsGridViewShown, thumbSize);
         }
 
         renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
@@ -136,6 +182,19 @@
         return renderRequestFlags;
     }
 
+    protected int renderLabel(GLCanvas canvas, AlbumEntry entry, int width,
+            int height) {
+        Texture content = checkLabelTexture(entry.labelTexture);
+        if (content == null) {
+            content = mWaitLoadingTexture;
+        }
+        int b = AlbumLabelMaker.getBorderSize();
+        int h = mLabelSpec.labelBackgroundHeight;
+        content.draw(canvas, -b, height - h + b, width + b + b, h);
+
+        return 0;
+    }
+
     private int renderOverlay(GLCanvas canvas, int index,
             AlbumSlidingWindow.AlbumEntry entry, int width, int height) {
         int renderRequestFlags = 0;
@@ -152,21 +211,30 @@
             }
         } else if ((entry.path != null) && (mHighlightItemPath == entry.path)) {
             drawSelectedFrame(canvas, width, height);
-        } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.path)) {
+        } else if (mInSelectionMode
+                && mSelectionManager.isItemSelected(entry.path)) {
             drawSelectedFrame(canvas, width, height);
         }
         return renderRequestFlags;
     }
 
+    private static Texture checkLabelTexture(Texture texture) {
+        return ((texture instanceof UploadedTexture) && ((UploadedTexture) texture)
+                .isUploading()) ? null : texture;
+    }
+
     private class MyDataModelListener implements AlbumSlidingWindow.Listener {
         @Override
         public void onContentChanged() {
             mSlotView.invalidate();
+
         }
 
         @Override
         public void onSizeChanged(int size) {
             mSlotView.setSlotCount(size);
+            mSlotView.invalidate();
+
         }
     }
 
@@ -192,7 +260,9 @@
 
     @Override
     public void onSlotSizeChanged(int width, int height) {
-        // Do nothing
+        if (!mIsGridViewShown && mDataWindow != null) {
+            mDataWindow.onSlotSizeChanged(width, height);
+        }
     }
 
     public void setSlotFilter(SlotFilter slotFilter) {
diff --git a/src/com/android/gallery3d/ui/BaseDialogFragment.java b/src/com/android/gallery3d/ui/BaseDialogFragment.java
new file mode 100644
index 0000000..a421578
--- /dev/null
+++ b/src/com/android/gallery3d/ui/BaseDialogFragment.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.ui;
+
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+
+public class BaseDialogFragment extends DialogFragment {
+
+    @Override
+    public void show(FragmentManager manager, String tag) {
+        try {
+            super.show(manager, tag);
+        } catch(IllegalStateException e) {
+            FragmentTransaction transaction = manager.beginTransaction();
+            transaction.add(this, tag);
+            transaction.commitAllowingStateLoss();
+        }
+    }
+
+    @Override
+    public int show(FragmentTransaction transaction, String tag) {
+        try {
+            return super.show(transaction, tag);
+        } catch (IllegalStateException e) {
+            transaction.add(this, tag);
+            return transaction.commitAllowingStateLoss();
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/ui/DetailsHelper.java b/src/com/android/gallery3d/ui/DetailsHelper.java
index 47296f6..167615b 100644
--- a/src/com/android/gallery3d/ui/DetailsHelper.java
+++ b/src/com/android/gallery3d/ui/DetailsHelper.java
@@ -20,7 +20,7 @@
 import android.graphics.BitmapFactory;
 import android.view.View.MeasureSpec;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.data.MediaDetails;
 import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener;
@@ -139,6 +139,8 @@
                 return context.getString(R.string.exposure_time);
             case MediaDetails.INDEX_ISO:
                 return context.getString(R.string.iso);
+            case MediaDetails.INDEX_DATETIME_ORIGINAL:
+                return context.getString(R.string.record_time);
             default:
                 return "Unknown key" + key;
         }
diff --git a/src/com/android/gallery3d/ui/DialogDetailsView.java b/src/com/android/gallery3d/ui/DialogDetailsView.java
index 30fd1e1..5b3a016 100644
--- a/src/com/android/gallery3d/ui/DialogDetailsView.java
+++ b/src/com/android/gallery3d/ui/DialogDetailsView.java
@@ -21,7 +21,10 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.DialogInterface.OnDismissListener;
+import android.content.res.Resources;
+import android.text.TextUtils;
 import android.text.format.Formatter;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -29,18 +32,22 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.MediaDetails;
+import com.android.gallery3d.exif.ExifInterface;
 import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener;
 import com.android.gallery3d.ui.DetailsHelper.CloseListener;
 import com.android.gallery3d.ui.DetailsHelper.DetailsSource;
 import com.android.gallery3d.ui.DetailsHelper.DetailsViewContainer;
 import com.android.gallery3d.ui.DetailsHelper.ResolutionResolvingListener;
 
+import java.text.DateFormat;
 import java.text.DecimalFormat;
+import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.Locale;
 import java.util.Map.Entry;
 
@@ -53,7 +60,7 @@
     private MediaDetails mDetails;
     private final DetailsSource mSource;
     private int mIndex;
-    private Dialog mDialog;
+    private AlertDialog mDialog;
     private CloseListener mListener;
 
     public DialogDetailsView(AbstractGalleryActivity activity, DetailsSource source) {
@@ -93,17 +100,19 @@
         ListView detailsList = (ListView) LayoutInflater.from(mActivity.getAndroidContext()).inflate(
                 R.layout.details_list, null, false);
         detailsList.setAdapter(mAdapter);
-        mDialog = new AlertDialog.Builder(mActivity)
-            .setView(detailsList)
-            .setTitle(title)
-            .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
-                @Override
-                public void onClick(DialogInterface dialog, int whichButton) {
-                    mDialog.dismiss();
-                }
-            })
-            .create();
+        AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
 
+         builder.setView(detailsList);
+        builder.setTitle(title);
+        builder.setPositiveButton(R.string.close,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int whichButton) {
+                        mDialog.dismiss();
+                    }
+                });
+
+        mDialog = builder.create();
         mDialog.setOnDismissListener(new OnDismissListener() {
             @Override
             public void onDismiss(DialogInterface dialog) {
@@ -112,6 +121,24 @@
                 }
             }
         });
+        mDialog.show();
+        Resources r = mActivity.getResources();
+
+        int buttonColor = r.getColor(R.color.dialog_button_color);
+        mDialog.getButton(DialogInterface.BUTTON_POSITIVE)
+                .setTextSize(TypedValue.COMPLEX_UNIT_SP,14);
+        mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(
+                buttonColor);
+
+        builder.setView(detailsList);
+        builder.setTitle(title);
+        builder.setPositiveButton(R.string.close,
+                new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int whichButton) {
+                        mDialog.dismiss();
+                    }
+                });
     }
 
 
@@ -131,6 +158,15 @@
             setDetails(context, details);
         }
 
+        private String exifDateToFormatedDate(String exifDt) {
+            try {
+                Date date = ExifInterface.DATETIME_FORMAT.parse(exifDt);
+                return DateFormat.getDateTimeInstance().format(date);
+            } catch (ParseException e) {
+                return exifDt;
+            }
+        }
+
         private void setDetails(Context context, MediaDetails details) {
             boolean resolutionIsValid = true;
             String path = null;
@@ -221,14 +257,20 @@
                     case MediaDetails.INDEX_ORIENTATION:
                         value = toLocalInteger(detail.getValue());
                         break;
+                    case MediaDetails.INDEX_DATETIME_ORIGINAL:
+                        value = exifDateToFormatedDate(detail.getValue().toString());
+                        break;
                     default: {
                         Object valueObj = detail.getValue();
                         // This shouldn't happen, log its key to help us diagnose the problem.
                         if (valueObj == null) {
-                            Utils.fail("%s's value is Null",
-                                    DetailsHelper.getDetailsName(context, detail.getKey()));
+//                            Utils.fail("%s's value is Null",
+//                                    DetailsHelper.getDetailsName(context, detail.getKey()));
+//                            DetailsHelper.getDetailsName(context, detail.getKey()) is null
+                            value = "Null";
+                        } else {
+                            value = valueObj.toString();
                         }
-                        value = valueObj.toString();
                     }
                 }
                 int key = detail.getKey();
@@ -236,13 +278,20 @@
                     value = String.format("%s: %s %s", DetailsHelper.getDetailsName(
                             context, key), value, context.getString(details.getUnit(key)));
                 } else {
-                    value = String.format("%s: %s", DetailsHelper.getDetailsName(
-                            context, key), value);
+                    if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                            .getLayoutDirectionFromLocale(Locale.getDefault())
+                            && (key == MediaDetails.INDEX_PATH)) {
+                        value = String.format("%s : \n%s",
+                                DetailsHelper.getDetailsName(context, key), value);
+                    } else {
+                        value = String.format("%s: %s", DetailsHelper.getDetailsName(context, key),
+                                value);
+                    }
                 }
                 mItems.add(value);
-            }
-            if (!resolutionIsValid) {
-                DetailsHelper.resolveResolution(path, this);
+                if (!resolutionIsValid) {
+                    DetailsHelper.resolveResolution(path, this);
+                }
             }
         }
 
diff --git a/src/com/android/gallery3d/ui/EdgeEffect.java b/src/com/android/gallery3d/ui/EdgeEffect.java
index 87ff0c5..1463655 100644
--- a/src/com/android/gallery3d/ui/EdgeEffect.java
+++ b/src/com/android/gallery3d/ui/EdgeEffect.java
@@ -22,7 +22,7 @@
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.ResourceTexture;
 
diff --git a/src/com/android/gallery3d/ui/EdgeView.java b/src/com/android/gallery3d/ui/EdgeView.java
old mode 100644
new mode 100755
index 051de18..dc648b4
--- a/src/com/android/gallery3d/ui/EdgeView.java
+++ b/src/com/android/gallery3d/ui/EdgeView.java
@@ -49,6 +49,10 @@
         }
     }
 
+    public void release () {
+        mEffect = null;
+    }
+
     @Override
     protected void onLayout(
             boolean changeSize, int left, int top, int right, int bottom) {
diff --git a/src/com/android/gallery3d/ui/GLRoot.java b/src/com/android/gallery3d/ui/GLRoot.java
old mode 100644
new mode 100755
index 33a82ea..50ba2e4
--- a/src/com/android/gallery3d/ui/GLRoot.java
+++ b/src/com/android/gallery3d/ui/GLRoot.java
@@ -28,7 +28,7 @@
     // Mainly used for uploading textures.
     public static interface OnGLIdleListener {
         public boolean onGLIdle(
-                GLCanvas canvas, boolean renderRequested);
+                GLCanvas canvas, boolean renderRequested, long dueTime);
     }
 
     public void addOnGLIdleListener(OnGLIdleListener listener);
@@ -45,8 +45,6 @@
     public int getDisplayRotation();
     public int getCompensation();
     public Matrix getCompensationMatrix();
-    public void freeze();
-    public void unfreeze();
     public void setLightsOutMode(boolean enabled);
 
     public Context getContext();
diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java
old mode 100644
new mode 100755
index dc898d8..579fd05
--- a/src/com/android/gallery3d/ui/GLRootView.java
+++ b/src/com/android/gallery3d/ui/GLRootView.java
@@ -29,7 +29,7 @@
 import android.view.SurfaceHolder;
 import android.view.View;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.anim.CanvasAnimation;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
@@ -78,6 +78,8 @@
     private static final int FLAG_INITIALIZED = 1;
     private static final int FLAG_NEED_LAYOUT = 2;
 
+    private static final long FRAME_INTERVAL = 16000000;
+
     private GL11 mGL;
     private GLCanvas mCanvas;
     private GLView mContentView;
@@ -103,14 +105,13 @@
     private final IdleRunner mIdleRunner = new IdleRunner();
 
     private final ReentrantLock mRenderLock = new ReentrantLock();
-    private final Condition mFreezeCondition =
-            mRenderLock.newCondition();
-    private boolean mFreeze;
 
     private long mLastDrawFinishTime;
     private boolean mInDownState = false;
     private boolean mFirstDraw = true;
 
+    private long mDueTime;
+
     public GLRootView(Context context) {
         this(context, null);
     }
@@ -339,6 +340,7 @@
 
     @Override
     public void onDrawFrame(GL10 gl) {
+        mDueTime = System.nanoTime() + FRAME_INTERVAL;
         AnimationTime.update();
         long t0;
         if (DEBUG_PROFILE_SLOW_ONLY) {
@@ -347,10 +349,6 @@
         }
         mRenderLock.lock();
 
-        while (mFreeze) {
-            mFreezeCondition.awaitUninterruptibly();
-        }
-
         try {
             onDrawFrameLocked(gl);
         } finally {
@@ -499,9 +497,15 @@
                 listener = mIdleListeners.removeFirst();
             }
             mRenderLock.lock();
-            boolean keepInQueue;
+            boolean keepInQueue = false;
             try {
-                keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested);
+                if (mCanvas != null) {
+                    long t = System.nanoTime();
+                    if (mDueTime < t) {
+                        mDueTime = t + FRAME_INTERVAL / 2;
+                    }
+                    keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested, mDueTime);
+                }
             } finally {
                 mRenderLock.unlock();
             }
@@ -531,7 +535,6 @@
 
     @Override
     public void onPause() {
-        unfreeze();
         super.onPause();
         if (DEBUG_PROFILE) {
             Log.d(TAG, "Stop profiling");
@@ -561,20 +564,6 @@
         return mCompensationMatrix;
     }
 
-    @Override
-    public void freeze() {
-        mRenderLock.lock();
-        mFreeze = true;
-        mRenderLock.unlock();
-    }
-
-    @Override
-    public void unfreeze() {
-        mRenderLock.lock();
-        mFreeze = false;
-        mFreezeCondition.signalAll();
-        mRenderLock.unlock();
-    }
 
     @Override
     @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@@ -591,40 +580,4 @@
         setSystemUiVisibility(flags);
     }
 
-    // We need to unfreeze in the following methods and in onPause().
-    // These methods will wait on GLThread. If we have freezed the GLRootView,
-    // the GLThread will wait on main thread to call unfreeze and cause dead
-    // lock.
-    @Override
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        unfreeze();
-        super.surfaceChanged(holder, format, w, h);
-    }
-
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
-        unfreeze();
-        super.surfaceCreated(holder);
-    }
-
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        unfreeze();
-        super.surfaceDestroyed(holder);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        unfreeze();
-        super.onDetachedFromWindow();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            unfreeze();
-        } finally {
-            super.finalize();
-        }
-    }
 }
diff --git a/src/com/android/gallery3d/ui/ManageCacheDrawer.java b/src/com/android/gallery3d/ui/ManageCacheDrawer.java
index d210bd1..68a201b 100644
--- a/src/com/android/gallery3d/ui/ManageCacheDrawer.java
+++ b/src/com/android/gallery3d/ui/ManageCacheDrawer.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.data.DataSourceType;
 import com.android.gallery3d.data.MediaSet;
diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java
index 22b3b57..bb8f1b1 100644
--- a/src/com/android/gallery3d/ui/MenuExecutor.java
+++ b/src/com/android/gallery3d/ui/MenuExecutor.java
@@ -24,13 +24,17 @@
 import android.content.DialogInterface.OnCancelListener;
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
+//import android.drm.DrmHelper;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
 import androidx.print.PrintHelper;
 import android.view.Menu;
 import android.view.MenuItem;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.data.DataManager;
@@ -44,6 +48,7 @@
 import com.android.gallery3d.util.ThreadPool.JobContext;
 
 import java.util.ArrayList;
+import java.util.List;
 
 public class MenuExecutor {
     private static final String TAG = "MenuExecutor";
@@ -62,6 +67,7 @@
     // wait the operation to finish when we want to stop it.
     private boolean mWaitOnStop;
     private boolean mPaused;
+    private boolean isLeaving = false;
 
     private final AbstractGalleryActivity mActivity;
     private final SelectionManager mSelectionManager;
@@ -179,11 +185,11 @@
         boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0;
         boolean supportPrint = (supported & MediaObject.SUPPORT_PRINT) != 0;
         supportPrint &= PrintHelper.systemSupportsPrint();
-
+        boolean supportDrmInfo = (supported & MediaObject.SUPPORT_DRM_INFO) != 0;
         setMenuItemVisible(menu, R.id.action_delete, supportDelete);
-        setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
-        setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
-        setMenuItemVisible(menu, R.id.action_crop, supportCrop);
+        //setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate);
+        //setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate);
+        //setMenuItemVisible(menu, R.id.action_crop, supportCrop);
         setMenuItemVisible(menu, R.id.action_trim, supportTrim);
         setMenuItemVisible(menu, R.id.action_mute, supportMute);
         // Hide panorama until call to updateMenuForPanorama corrects it
@@ -195,14 +201,15 @@
         // setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit);
         setMenuItemVisible(menu, R.id.action_details, supportInfo);
         setMenuItemVisible(menu, R.id.print, supportPrint);
+        setMenuItemVisible(menu, R.id.action_drm_info, supportDrmInfo);
     }
 
     public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360,
             boolean disablePanorama360Options) {
         setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360);
         if (disablePanorama360Options) {
-            setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
-            setMenuItemVisible(menu, R.id.action_rotate_cw, false);
+            //setMenuItemVisible(menu, R.id.action_rotate_ccw, false);
+            //setMenuItemVisible(menu, R.id.action_rotate_cw, false);
         }
     }
 
@@ -213,17 +220,28 @@
 
     private Path getSingleSelectedPath() {
         ArrayList<Path> ids = mSelectionManager.getSelected(true);
-        Utils.assertTrue(ids.size() == 1);
-        return ids.get(0);
+        if (ids.size() != 1)
+            return null;
+         return ids.get(0);
     }
 
     private Intent getIntentBySingleSelectedPath(String action) {
         DataManager manager = mActivity.getDataManager();
         Path path = getSingleSelectedPath();
+        if (path == null)
+            return null;
         String mimeType = getMimeType(manager.getMediaType(path));
         return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType);
     }
 
+    public void setLeaving(boolean leaving) {
+        isLeaving = leaving;
+    }
+
+    public boolean isLeaving() {
+        return isLeaving;
+    }
+
     private void onMenuClicked(int action, ProgressListener listener) {
         onMenuClicked(action, listener, false, true);
     }
@@ -234,43 +252,84 @@
         switch (action) {
             case R.id.action_select_all:
                 if (mSelectionManager.inSelectAllMode()) {
+                    isLeaving = true;
                     mSelectionManager.deSelectAll();
                 } else {
                     mSelectionManager.selectAll();
                 }
                 return;
-            case R.id.action_crop: {
+            /*case R.id.action_crop: {
                 Intent intent = getIntentBySingleSelectedPath(CropActivity.CROP_ACTION);
                 ((Activity) mActivity).startActivity(intent);
                 return;
-            }
+            }*/
             case R.id.action_edit: {
-                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT)
-                        .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                ((Activity) mActivity).startActivity(Intent.createChooser(intent, null));
+                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT);
+                if (intent != null) {
+                    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+                    List<ResolveInfo> resolveInfoList = mActivity.getPackageManager()
+                            .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+                    if (resolveInfoList != null && resolveInfoList.size() > 0) {
+                        if (resolveInfoList.size() == 1) {
+                            // only one app can resolve intent, don't use createChooser.
+                            mActivity.startActivity(intent);
+                        } else {
+                            mActivity.startActivity(Intent.createChooser(intent, null));
+                        }
+                    }
+                }
                 return;
             }
             case R.id.action_setas: {
-                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA)
-                        .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                intent.putExtra("mimeType", intent.getType());
-                Activity activity = mActivity;
-                activity.startActivity(Intent.createChooser(
-                        intent, activity.getString(R.string.set_as)));
+                Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA);
+                if (intent != null) {
+                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                    intent.putExtra("mimeType", intent.getType());
+
+                    // DRM files can be set as wallpaper only. Don't show other options
+                    // to set as.
+                    Uri uri = intent.getData();
+//                if (DrmHelper.isDrmFile(DrmHelper.getFilePath(mActivity, uri))) {
+//                    intent.setPackage("com.android.gallery3d");
+//                }
+
+                    Activity activity = mActivity;
+                    mActivity.isTopMenuShow = true;
+                    activity.startActivity(Intent.createChooser(
+                            intent, activity.getString(R.string.set_as)));
+                }
                 return;
             }
             case R.id.action_delete:
                 title = R.string.delete;
                 break;
-            case R.id.action_rotate_cw:
+            case R.id.photopage_bottom_control_delete:
+                title = R.string.delete;
+                break;
+            /*case R.id.action_rotate_cw:
                 title = R.string.rotate_right;
                 break;
             case R.id.action_rotate_ccw:
                 title = R.string.rotate_left;
-                break;
+                break;*/
             case R.id.action_show_on_map:
                 title = R.string.show_on_map;
                 break;
+//            case R.id.action_drm_info:
+//                DataManager manager = mActivity.getDataManager();
+//                Path path = getSingleSelectedPath();
+//                Uri uri = manager.getContentUri(path);
+//                String filepath = null;
+//                String scheme = uri.getScheme();
+//                if ("file".equals(scheme)) {
+//                    filepath = uri.getPath();
+//                } else {
+//                    filepath = DrmHelper.getFilePath(mActivity, uri);
+//                }
+//                DrmHelper.showDrmInfo(mActivity, filepath);
+//                title = R.string.drm_license_info;
+//                break;
             default:
                 return;
         }
@@ -310,7 +369,14 @@
 
     public void onMenuClicked(MenuItem menuItem, String confirmMsg,
             final ProgressListener listener) {
-        final int action = menuItem.getItemId();
+        final int action;
+        if (menuItem == null) {
+            action = R.id.photopage_bottom_control_delete;
+        }
+        else
+        {
+           action = menuItem.getItemId();
+        }
 
         if (confirmMsg != null) {
             if (listener != null) listener.onConfirmDialogShown();
@@ -376,12 +442,15 @@
             case R.id.action_delete:
                 manager.delete(path);
                 break;
-            case R.id.action_rotate_cw:
+            case R.id.photopage_bottom_control_delete:
+                manager.delete(path);
+                break;
+            /*case R.id.action_rotate_cw:
                 manager.rotate(path, 90);
                 break;
             case R.id.action_rotate_ccw:
                 manager.rotate(path, -90);
-                break;
+                break;*/
             case R.id.action_toggle_full_caching: {
                 MediaObject obj = manager.getMediaObject(path);
                 int cacheFlag = obj.getCacheFlag();
diff --git a/src/com/android/gallery3d/ui/Paper.java b/src/com/android/gallery3d/ui/Paper.java
deleted file mode 100644
index b36f5c3..0000000
--- a/src/com/android/gallery3d/ui/Paper.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gallery3d.ui;
-
-import android.graphics.Rect;
-import android.opengl.Matrix;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-
-import com.android.gallery3d.common.Utils;
-
-// This class does the overscroll effect.
-class Paper {
-    @SuppressWarnings("unused")
-    private static final String TAG = "Paper";
-    private static final int ROTATE_FACTOR = 4;
-    private EdgeAnimation mAnimationLeft = new EdgeAnimation();
-    private EdgeAnimation mAnimationRight = new EdgeAnimation();
-    private int mWidth;
-    private float[] mMatrix = new float[16];
-
-    public void overScroll(float distance) {
-        distance /= mWidth;  // make it relative to width
-        if (distance < 0) {
-            mAnimationLeft.onPull(-distance);
-        } else {
-            mAnimationRight.onPull(distance);
-        }
-    }
-
-    public void edgeReached(float velocity) {
-        velocity /= mWidth;  // make it relative to width
-        if (velocity < 0) {
-            mAnimationRight.onAbsorb(-velocity);
-        } else {
-            mAnimationLeft.onAbsorb(velocity);
-        }
-    }
-
-    public void onRelease() {
-        mAnimationLeft.onRelease();
-        mAnimationRight.onRelease();
-    }
-
-    public boolean advanceAnimation() {
-        // Note that we use "|" because we want both animations get updated.
-        return mAnimationLeft.update() | mAnimationRight.update();
-    }
-
-    public void setSize(int width, int height) {
-        mWidth = width;
-    }
-
-    public float[] getTransform(Rect rect, float scrollX) {
-        float left = mAnimationLeft.getValue();
-        float right = mAnimationRight.getValue();
-        float screenX = rect.centerX() - scrollX;
-        // We linearly interpolate the value [left, right] for the screenX
-        // range int [-1/4, 5/4]*mWidth. So if part of the thumbnail is outside
-        // the screen, we still get some transform.
-        float x = screenX + mWidth / 4;
-        int range = 3 * mWidth / 2;
-        float t = ((range - x) * left - x * right) / range;
-        // compress t to the range (-1, 1) by the function
-        // f(t) = (1 / (1 + e^-t) - 0.5) * 2
-        // then multiply by 90 to make the range (-45, 45)
-        float degrees =
-                (1 / (1 + (float) Math.exp(-t * ROTATE_FACTOR)) - 0.5f) * 2 * -45;
-        Matrix.setIdentityM(mMatrix, 0);
-        Matrix.translateM(mMatrix, 0, mMatrix, 0, rect.centerX(), rect.centerY(), 0);
-        Matrix.rotateM(mMatrix, 0, degrees, 0, 1, 0);
-        Matrix.translateM(mMatrix, 0, mMatrix, 0, -rect.width() / 2, -rect.height() / 2, 0);
-        return mMatrix;
-    }
-}
-
-// This class follows the structure of frameworks's EdgeEffect class.
-class EdgeAnimation {
-    @SuppressWarnings("unused")
-    private static final String TAG = "EdgeAnimation";
-
-    private static final int STATE_IDLE = 0;
-    private static final int STATE_PULL = 1;
-    private static final int STATE_ABSORB = 2;
-    private static final int STATE_RELEASE = 3;
-
-    // Time it will take the effect to fully done in ms
-    private static final int ABSORB_TIME = 200;
-    private static final int RELEASE_TIME = 500;
-
-    private static final float VELOCITY_FACTOR = 0.1f;
-
-    private final Interpolator mInterpolator;
-
-    private int mState;
-    private float mValue;
-
-    private float mValueStart;
-    private float mValueFinish;
-    private long mStartTime;
-    private long mDuration;
-
-    public EdgeAnimation() {
-        mInterpolator = new DecelerateInterpolator();
-        mState = STATE_IDLE;
-    }
-
-    private void startAnimation(float start, float finish, long duration,
-            int newState) {
-        mValueStart = start;
-        mValueFinish = finish;
-        mDuration = duration;
-        mStartTime = now();
-        mState = newState;
-    }
-
-    // The deltaDistance's magnitude is in the range of -1 (no change) to 1.
-    // The value 1 is the full length of the view. Negative values means the
-    // movement is in the opposite direction.
-    public void onPull(float deltaDistance) {
-        if (mState == STATE_ABSORB) return;
-        mValue = Utils.clamp(mValue + deltaDistance, -1.0f, 1.0f);
-        mState = STATE_PULL;
-    }
-
-    public void onRelease() {
-        if (mState == STATE_IDLE || mState == STATE_ABSORB) return;
-        startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE);
-    }
-
-    public void onAbsorb(float velocity) {
-        float finish = Utils.clamp(mValue + velocity * VELOCITY_FACTOR,
-                -1.0f, 1.0f);
-        startAnimation(mValue, finish, ABSORB_TIME, STATE_ABSORB);
-    }
-
-    public boolean update() {
-        if (mState == STATE_IDLE) return false;
-        if (mState == STATE_PULL) return true;
-
-        float t = Utils.clamp((float)(now() - mStartTime) / mDuration, 0.0f, 1.0f);
-        /* Use linear interpolation for absorb, quadratic for others */
-        float interp = (mState == STATE_ABSORB)
-                ? t : mInterpolator.getInterpolation(t);
-
-        mValue = mValueStart + (mValueFinish - mValueStart) * interp;
-
-        if (t >= 1.0f) {
-            switch (mState) {
-                case STATE_ABSORB:
-                    startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE);
-                    break;
-                case STATE_RELEASE:
-                    mState = STATE_IDLE;
-                    break;
-            }
-        }
-
-        return true;
-    }
-
-    public float getValue() {
-        return mValue;
-    }
-
-    private long now() {
-        return AnimationTime.get();
-    }
-}
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java
old mode 100644
new mode 100755
index e8c706f..246e647
--- a/src/com/android/gallery3d/ui/PhotoView.java
+++ b/src/com/android/gallery3d/ui/PhotoView.java
@@ -27,7 +27,7 @@
 import android.view.View.MeasureSpec;
 import android.view.animation.AccelerateInterpolator;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.common.Utils;
@@ -92,6 +92,9 @@
         // Returns true if the item is a Video.
         public boolean isVideo(int offset);
 
+        // Returns true if the item is a Gif.
+        public boolean isGif(int offset);
+
         // Returns true if the item can be deleted.
         public boolean isDeletable(int offset);
 
@@ -124,7 +127,6 @@
         public void onFullScreenChanged(boolean full);
         public void onActionBarAllowed(boolean allowed);
         public void onActionBarWanted();
-        public void onCurrentImageUpdated();
         public void onDeleteImage(Path path, int offset);
         public void onUndoDeleteImage();
         public void onCommitDeleteImage();
@@ -200,6 +202,8 @@
     private EdgeView mEdgeView;
     private UndoBarView mUndoBar;
     private Texture mVideoPlayIcon;
+    private Texture mDrmIcon;
+    private int mVideoPlayIconSize = 0;
 
     private SynchronizedHandler mHandler;
 
@@ -302,7 +306,10 @@
                 mEdgeView.onAbsorb(velocity, direction);
             }
         });
-        mVideoPlayIcon = new ResourceTexture(mContext, R.drawable.ic_control_play);
+        mVideoPlayIcon = new ResourceTexture(mContext, R.drawable.play_detail);
+        mVideoPlayIconSize = mContext.getResources().getDimensionPixelSize(
+                R.dimen.photo_view_video_icon_size);
+        mDrmIcon = new ResourceTexture(mContext, R.drawable.drm_image);
         for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) {
             if (i == 0) {
                 mPictures.put(i, new FullPicture());
@@ -460,9 +467,6 @@
     }
 
     public void notifyImageChange(int index) {
-        if (index == 0) {
-            mListener.onCurrentImageUpdated();
-        }
         mPictures.get(index).reload();
         setPictureSize(index);
         invalidate();
@@ -593,7 +597,6 @@
         private boolean mIsCamera;
         private boolean mIsPanorama;
         private boolean mIsStaticCamera;
-        private boolean mIsVideo;
         private boolean mIsDeletable;
         private int mLoadingState = Model.LOADING_INIT;
         private Size mSize = new Size();
@@ -606,7 +609,6 @@
             mIsCamera = mModel.isCamera(0);
             mIsPanorama = mModel.isPanorama(0);
             mIsStaticCamera = mModel.isStaticCamera(0);
-            mIsVideo = mModel.isVideo(0);
             mIsDeletable = mModel.isDeletable(0);
             mLoadingState = mModel.getLoadingState(0);
             setScreenNail(mModel.getScreenNail(0));
@@ -731,11 +733,23 @@
             // Draw the play video icon and the message.
             canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f));
             int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f);
-            if (mIsVideo) drawVideoPlayIcon(canvas, s);
-            if (mLoadingState == Model.LOADING_FAIL) {
+            //Full pic locates at index 0 of the array in PhotoDataAdapter
+            if (mModel.isVideo(0) || mModel.isGif(0)) {
+                drawVideoPlayIcon(canvas, s);
+            }
+            if (mLoadingState == Model.LOADING_FAIL ) {
                 drawLoadingFailMessage(canvas);
             }
 
+//            if (getFilmMode()) {
+//                MediaItem item = mModel.getMediaItem(0);
+//                if (item != null) {
+//                    if (DrmHelper.isDrmFile(item.getFilePath())) {
+//                        drawDrmIcon(canvas, s);
+//                    }
+//                }
+//            }
+
             // Draw a debug indicator showing which picture has focus (index ==
             // 0).
             //canvas.fillRect(-10, -10, 20, 20, 0x80FF00FF);
@@ -774,7 +788,6 @@
         private boolean mIsCamera;
         private boolean mIsPanorama;
         private boolean mIsStaticCamera;
-        private boolean mIsVideo;
         private boolean mIsDeletable;
         private int mLoadingState = Model.LOADING_INIT;
         private Size mSize = new Size();
@@ -788,7 +801,6 @@
             mIsCamera = mModel.isCamera(mIndex);
             mIsPanorama = mModel.isPanorama(mIndex);
             mIsStaticCamera = mModel.isStaticCamera(mIndex);
-            mIsVideo = mModel.isVideo(mIndex);
             mIsDeletable = mModel.isDeletable(mIndex);
             mLoadingState = mModel.getLoadingState(mIndex);
             setScreenNail(mModel.getScreenNail(mIndex));
@@ -852,10 +864,21 @@
                 invalidate();
             }
             int s = Math.min(drawW, drawH);
-            if (mIsVideo) drawVideoPlayIcon(canvas, s);
-            if (mLoadingState == Model.LOADING_FAIL) {
+            if (mModel.isVideo(mIndex) || mModel.isGif(mIndex)) {
+                drawVideoPlayIcon(canvas, s);
+            }
+
+            if (mLoadingState == Model.LOADING_FAIL ) {
                 drawLoadingFailMessage(canvas);
             }
+
+//            MediaItem item = mModel.getMediaItem(mIndex);
+//            if (item != null) {
+//                if (DrmHelper.isDrmFile(item.getFilePath())) {
+//                    drawDrmIcon(canvas, s);
+//                }
+//            }
+
             canvas.restore();
         }
 
@@ -917,11 +940,18 @@
 
     // Draw the video play icon (in the place where the spinner was)
     private void drawVideoPlayIcon(GLCanvas canvas, int side) {
-        int s = side / ICON_RATIO;
+        int s = mVideoPlayIconSize;
         // Draw the video play icon at the center
         mVideoPlayIcon.draw(canvas, -s / 2, -s / 2, s, s);
     }
 
+    // Draw the Drm lock icon (in the place where the spinner was)
+    private void drawDrmIcon(GLCanvas canvas, int side) {
+        int s = side / ICON_RATIO;
+        // Draw the Drm lock icon at the center
+        mDrmIcon.draw(canvas, -s / 2, -s / 2, s, s);
+    }
+
     // Draw the "no thumbnail" message
     private void drawLoadingFailMessage(GLCanvas canvas) {
         StringTexture m = mNoThumbnailText;
@@ -1023,8 +1053,16 @@
             // onDoubleTap happened on the second ACTION_DOWN.
             // We need to ignore the next UP event.
             mIgnoreUpEvent = true;
-            if (scale <= .75f || controller.isAtMinimalScale()) {
-                controller.zoomIn(x, y, Math.max(1.0f, scale * 1.5f));
+            Log.d(TAG, "onDoubleTap scale=" + scale);
+            if (scale <= .15f) {
+                //mPictures.get(0).setScreenNail(mBigSNail);
+                controller.zoomIn(x, y, Math.max(0.2f, scale * 1.5f));
+            } else if (scale <= .45f) {
+                controller.zoomIn(x, y, Math.max(0.6f, scale * 1.5f));
+            } else if (scale <= .75f) {
+                controller.zoomIn(x, y, Math.max(1f, scale * 1.5f));
+            } else if (controller.isAtMinimalScale()) {
+                controller.zoomIn(x, y, scale * 1.5f);
             } else {
                 controller.resetToFullView();
             }
@@ -1128,6 +1166,7 @@
         }
 
         private void deleteAfterAnimation(int duration) {
+            if (mHandler.hasMessages(MSG_DELETE_ANIMATION_DONE)) return;
             MediaItem item = mModel.getMediaItem(mTouchBoxIndex);
             if (item == null) return;
             mListener.onCommitDeleteImage();
@@ -1147,6 +1186,8 @@
             if (mIgnoreScalingGesture) {
                 return true;
             }
+            // We ignore other scale begin notification if film mode has been changed.
+            if (mModeChanged) return true;
             mPositionController.beginScale(focusX, focusY);
             // We can change mode if we are in film mode, or we are in page
             // mode and at minimal scale.
@@ -1273,7 +1314,9 @@
             if (mIgnoreSwipingGesture) return;
 
             mHolding &= ~HOLD_TOUCH_DOWN;
-            mEdgeView.onRelease();
+            if (mEdgeView != null) {
+                mEdgeView.onRelease();
+            }
 
             // If we scrolled in Y direction far enough, treat it as a delete
             // gesture.
@@ -1350,6 +1393,11 @@
         hideUndoBar();
     }
 
+    public void destroy() {
+        mEdgeView.release();
+        mEdgeView = null;
+    }
+
     public void resume() {
         mTileView.prepareTextures();
         mPositionController.skipToFinalPosition();
@@ -1854,4 +1902,5 @@
         }
         return effect;
     }
+
 }
diff --git a/src/com/android/gallery3d/ui/PopupList.java b/src/com/android/gallery3d/ui/PopupList.java
index 248f50b..37c0b87 100644
--- a/src/com/android/gallery3d/ui/PopupList.java
+++ b/src/com/android/gallery3d/ui/PopupList.java
@@ -17,7 +17,9 @@
 package com.android.gallery3d.ui;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.MeasureSpec;
@@ -31,7 +33,7 @@
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
@@ -152,11 +154,13 @@
     }
 
     private PopupWindow createPopupWindow() {
-        PopupWindow popup = new PopupWindow(mContext);
+        PopupWindow popup = new PopupWindow(mContext, null, android.R.attr.popupMenuStyle);
         popup.setOnDismissListener(mOnDismissListener);
+        popup.setBackgroundDrawable(new ColorDrawable(
+                mContext.getResources().getColor(R.color.white)));
 
-        popup.setBackgroundDrawable(mContext.getResources().getDrawable(
-                R.drawable.menu_dropdown_panel_holo_dark));
+//        popup.setBackgroundDrawable(mContext.getResources().getDrawable(
+//                R.drawable.menu_dropdown_panel_holo_dark));
 
         mContentList = new ListView(mContext, null,
                 android.R.attr.dropDownListViewStyle);
diff --git a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java b/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java
index ce672f2..290657a 100644
--- a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java
+++ b/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java
@@ -47,7 +47,7 @@
     }
 
     @Override
-    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
+    public boolean onGLIdle(GLCanvas canvas, boolean renderRequested, long dueTime) {
         if (!mCancelled) {
             try {
                 canvas.beginRenderTarget(mTexture);
@@ -69,12 +69,12 @@
         if (task.isCancelled()) return;
         GLRoot root = activity.getGLRoot();
         RawTexture texture = null;
-        root.unlockRenderThread();
+        root.lockRenderThread();
         try {
             root.addOnGLIdleListener(task);
             texture = task.get();
         } finally {
-            root.lockRenderThread();
+            root.unlockRenderThread();
         }
 
         if (texture == null) {
diff --git a/src/com/android/gallery3d/ui/ProgressSpinner.java b/src/com/android/gallery3d/ui/ProgressSpinner.java
index 1b31af2..1d2f3cb 100644
--- a/src/com/android/gallery3d/ui/ProgressSpinner.java
+++ b/src/com/android/gallery3d/ui/ProgressSpinner.java
@@ -18,7 +18,7 @@
 
 import android.content.Context;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.ResourceTexture;
 
diff --git a/src/com/android/gallery3d/ui/ScrollerHelper.java b/src/com/android/gallery3d/ui/ScrollerHelper.java
index aa68d19..bd06aa5 100644
--- a/src/com/android/gallery3d/ui/ScrollerHelper.java
+++ b/src/com/android/gallery3d/ui/ScrollerHelper.java
@@ -25,7 +25,6 @@
 public class ScrollerHelper {
     private OverScroller mScroller;
     private int mOverflingDistance;
-    private boolean mOverflingEnabled;
 
     public ScrollerHelper(Context context) {
         mScroller = new OverScroller(context);
@@ -33,10 +32,6 @@
         mOverflingDistance = configuration.getScaledOverflingDistance();
     }
 
-    public void setOverfling(boolean enabled) {
-        mOverflingEnabled = enabled;
-    }
-
     /**
      * Call this when you want to know the new location. The position will be
      * updated and can be obtained by getPosition(). Returns true if  the
@@ -78,7 +73,7 @@
                 velocity, 0,   // velocityX, velocityY
                 min, max,      // minX, maxX
                 0, 0,          // minY, maxY
-                mOverflingEnabled ? mOverflingDistance : 0, 0);
+                mOverflingDistance, 0);
     }
 
     // Returns the distance that over the scroll limit.
diff --git a/src/com/android/gallery3d/ui/SelectionManager.java b/src/com/android/gallery3d/ui/SelectionManager.java
old mode 100644
new mode 100755
index 0164a7a..da61bf1
--- a/src/com/android/gallery3d/ui/SelectionManager.java
+++ b/src/com/android/gallery3d/ui/SelectionManager.java
@@ -17,8 +17,12 @@
 package com.android.gallery3d.ui;
 
 import com.android.gallery3d.app.AbstractGalleryActivity;
+import com.android.gallery3d.app.AlbumSetDataLoader;
+import com.android.gallery3d.app.TimeLineDataLoader;
+import com.android.gallery3d.data.ContentListener;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.data.MediaSet;
 import com.android.gallery3d.data.Path;
 
@@ -26,7 +30,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
-public class SelectionManager {
+public class SelectionManager implements TimeLineDataLoader.DataListener, AlbumSetDataLoader.DataListener{
     @SuppressWarnings("unused")
     private static final String TAG = "SelectionManager";
 
@@ -43,6 +47,29 @@
     private boolean mInSelectionMode;
     private boolean mAutoLeave = true;
     private int mTotal;
+    /** mTotalSelectable is the count of items
+     * exclude not selectable such as Title item in TimeLine. */
+    private int mTotalSelectable;
+    private TimeLineDataLoader mTimeLineDataLoader;
+    private AlbumSetDataLoader mAlbumSetDataLoader;
+
+    @Override
+    public void onContentChanged(int index) {
+    }
+
+    @Override
+    public void onSizeChanged(int size) {
+        if (mInverseSelection) {
+            selectAll();
+        }
+    }
+
+    @Override
+    public void onSizeChanged() {
+        if (mInverseSelection) {
+            selectAll();
+        }
+    }
 
     public interface SelectionListener {
         public void onSelectionModeChange(int mode);
@@ -54,6 +81,7 @@
         mClickedSet = new HashSet<Path>();
         mIsAlbumSet = isAlbumSet;
         mTotal = -1;
+        mTotalSelectable = -1;
     }
 
     // Whether we will leave selection mode automatically once the number of
@@ -70,6 +98,7 @@
         mInverseSelection = true;
         mClickedSet.clear();
         mTotal = -1;
+        mTotalSelectable = -1;
         enterSelectionMode();
         if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE);
     }
@@ -93,6 +122,12 @@
 
         mInSelectionMode = true;
         if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE);
+        if (mAlbumSetDataLoader != null) {
+            mAlbumSetDataLoader.setModelListener(this);
+        }
+        if (mTimeLineDataLoader != null) {
+            mTimeLineDataLoader.setDataListener(this);
+        }
     }
 
     public void leaveSelectionMode() {
@@ -102,6 +137,12 @@
         mInverseSelection = false;
         mClickedSet.clear();
         if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE);
+        if (mAlbumSetDataLoader != null) {
+            mAlbumSetDataLoader.removeModelListener(this);
+        }
+        if (mTimeLineDataLoader != null) {
+            mTimeLineDataLoader.removeDataListener(this);
+        }
     }
 
     public boolean isItemSelected(Path itemId) {
@@ -119,10 +160,25 @@
         return mTotal;
     }
 
+    /**
+     * Some items is not selectable. such as Title item in TimeLine.
+     *
+     * @return total selectable count.
+     */
+    private int getTotalSelectableCount() {
+        if (mSourceMediaSet == null) return -1;
+        if (mTotalSelectable < 0) {
+            mTotalSelectable = mIsAlbumSet
+                    ? mSourceMediaSet.getSubMediaSetCount()
+                    : mSourceMediaSet.getSelectableItemCount();
+        }
+        return mTotalSelectable;
+    }
+
     public int getSelectedCount() {
         int count = mClickedSet.size();
         if (mInverseSelection) {
-            count = getTotalCount() - count;
+            count = getTotalSelectableCount() - count;
         }
         return count;
     }
@@ -147,6 +203,20 @@
         }
     }
 
+    public void toggleTimeLineSet(ArrayList<Path> paths) {
+        if (mClickedSet.containsAll(paths))
+            mClickedSet.removeAll(paths);
+        else {
+            enterSelectionMode();
+            mClickedSet.addAll(paths);
+        }
+        int count = getSelectedCount();
+        if (count == (mSourceMediaSet.getMediaItemCount() - mSourceMediaSet.getSubMediaSetCount()))
+            selectAll();
+        if (mListener != null) mListener.onSelectionChange(paths.get(0), isItemSelected(paths.get(0)));
+        if (count == 0 && mAutoLeave)
+            leaveSelectionMode();
+    }
     private static boolean expandMediaSet(ArrayList<Path> items, MediaSet set, int maxSelection) {
         int subCount = set.getSubMediaSetCount();
         for (int i = 0; i < subCount; i++) {
@@ -193,7 +263,7 @@
                                 return null;
                             }
                         } else {
-                            selected.add(id);
+                            addPathIfSelectable(selected, id);
                             if (selected.size() > maxSelection) {
                                 return null;
                             }
@@ -208,7 +278,7 @@
                             return null;
                         }
                     } else {
-                        selected.add(id);
+                        addPathIfSelectable(selected, id);
                         if (selected.size() > maxSelection) {
                             return null;
                         }
@@ -225,7 +295,7 @@
                     for (MediaItem item : list) {
                         Path id = item.getPath();
                         if (!mClickedSet.contains(id)) {
-                            selected.add(id);
+                            addPathIfSelectable(selected, id);
                             if (selected.size() > maxSelection) {
                                 return null;
                             }
@@ -235,7 +305,7 @@
                 }
             } else {
                 for (Path id : mClickedSet) {
-                    selected.add(id);
+                    addPathIfSelectable(selected, id);
                     if (selected.size() > maxSelection) {
                         return null;
                     }
@@ -245,8 +315,25 @@
         return selected;
     }
 
+    private void addPathIfSelectable(ArrayList<Path> selected, Path path) {
+        if (mDataManager != null) {
+            MediaObject mediaObject = mDataManager.getMediaObject(path);
+            if (mediaObject != null && mediaObject.isSelectable()) {
+                selected.add(path);
+            }
+        }
+    }
+
     public void setSourceMediaSet(MediaSet set) {
         mSourceMediaSet = set;
         mTotal = -1;
     }
+
+    public void setTimeLineDataLoader(TimeLineDataLoader loader) {
+        mTimeLineDataLoader = loader;
+    }
+
+    public void setAlbumSetDataLoader(AlbumSetDataLoader loader) {
+        mAlbumSetDataLoader = loader;
+    }
 }
diff --git a/src/com/android/gallery3d/ui/SelectionMenu.java b/src/com/android/gallery3d/ui/SelectionMenu.java
index 5b08283..07815cd 100644
--- a/src/com/android/gallery3d/ui/SelectionMenu.java
+++ b/src/com/android/gallery3d/ui/SelectionMenu.java
@@ -21,7 +21,7 @@
 import android.view.View.OnClickListener;
 import android.widget.Button;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.ui.PopupList.OnPopupItemClickListener;
 
 public class SelectionMenu implements OnClickListener {
@@ -31,6 +31,7 @@
     private final Context mContext;
     private final Button mButton;
     private final PopupList mPopupList;
+    private boolean isLeaving = false;
 
     public SelectionMenu(Context context, Button button, OnPopupItemClickListener listener) {
         mContext = context;
@@ -44,6 +45,7 @@
 
     @Override
     public void onClick(View v) {
+        if (isLeaving) return;
         mPopupList.show();
     }
 
@@ -58,4 +60,8 @@
     public void setTitle(CharSequence title) {
         mButton.setText(title);
     }
+
+    public void setLeaving(boolean leaving) {
+        isLeaving = leaving;
+    }
 }
diff --git a/src/com/android/gallery3d/ui/SlotView.java b/src/com/android/gallery3d/ui/SlotView.java
index bd0ffdc..65abffd 100644
--- a/src/com/android/gallery3d/ui/SlotView.java
+++ b/src/com/android/gallery3d/ui/SlotView.java
@@ -16,22 +16,28 @@
 
 package com.android.gallery3d.ui;
 
+import android.app.Activity;
 import android.graphics.Rect;
 import android.os.Handler;
+import android.text.TextUtils;
 import android.view.GestureDetector;
 import android.view.MotionEvent;
+import android.view.View;
 import android.view.animation.DecelerateInterpolator;
 
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.anim.Animation;
 import com.android.gallery3d.app.AbstractGalleryActivity;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.glrenderer.GLCanvas;
 
+import java.util.Locale;
+
 public class SlotView extends GLView {
     @SuppressWarnings("unused")
     private static final String TAG = "SlotView";
 
-    private static final boolean WIDE = true;
+    private static final boolean WIDE = false;
     private static final int INDEX_NONE = -1;
 
     public static final int RENDER_MORE_PASS = 1;
@@ -62,7 +68,6 @@
 
     private final GestureDetector mGestureDetector;
     private final ScrollerHelper mScroller;
-    private final Paper mPaper = new Paper();
 
     private Listener mListener;
     private UserInteractionListener mUIListener;
@@ -74,24 +79,24 @@
 
     // whether the down action happened while the view is scrolling.
     private boolean mDownInScrolling;
-    private int mOverscrollEffect = OVERSCROLL_3D;
     private final Handler mHandler;
 
     private SlotRenderer mRenderer;
 
     private int[] mRequestRenderSlots = new int[16];
 
-    public static final int OVERSCROLL_3D = 0;
-    public static final int OVERSCROLL_SYSTEM = 1;
-    public static final int OVERSCROLL_NONE = 2;
-
     // to prevent allocating memory
     private final Rect mTempRect = new Rect();
 
+    // Flag to check whether it is come from Photo Page.
+    private boolean isFromPhotoPage = false;
+    private Activity mActivity;
+
     public SlotView(AbstractGalleryActivity activity, Spec spec) {
         mGestureDetector = new GestureDetector(activity, new MyGestureListener());
         mScroller = new ScrollerHelper(activity);
         mHandler = new SynchronizedHandler(activity.getGLRoot());
+        mActivity = activity;
         setSlotSpec(spec);
     }
 
@@ -135,6 +140,13 @@
         setScrollPosition(position);
     }
 
+    /**
+     * Set the flag which used for check whether it is come from Photo Page.
+     */
+    public void setIsFromPhotoPage(boolean flag) {
+        isFromPhotoPage = flag;
+    }
+
     public void setScrollPosition(int position) {
         position = Utils.clamp(position, 0, mLayout.getScrollLimit());
         mScroller.setPosition(position);
@@ -161,9 +173,6 @@
                 (mLayout.getVisibleStart() + mLayout.getVisibleEnd()) / 2;
         mLayout.setSize(r - l, b - t);
         makeSlotVisible(visibleIndex);
-        if (mOverscrollEffect == OVERSCROLL_3D) {
-            mPaper.setSize(r - l, b - t);
-        }
     }
 
     public void startScatteringAnimation(RelativePosition position) {
@@ -208,7 +217,6 @@
                 mScroller.forceFinished();
                 break;
             case MotionEvent.ACTION_UP:
-                mPaper.onRelease();
                 invalidate();
                 break;
         }
@@ -223,11 +231,6 @@
         mUIListener = listener;
     }
 
-    public void setOverscrollEffect(int kind) {
-        mOverscrollEffect = kind;
-        mScroller.setOverfling(kind == OVERSCROLL_SYSTEM);
-    }
-
     private static int[] expandIntArray(int array[], int capacity) {
         while (array.length < capacity) {
             array = new int[array.length * 2];
@@ -248,25 +251,6 @@
         int oldX = mScrollX;
         updateScrollPosition(mScroller.getPosition(), false);
 
-        boolean paperActive = false;
-        if (mOverscrollEffect == OVERSCROLL_3D) {
-            // Check if an edge is reached and notify mPaper if so.
-            int newX = mScrollX;
-            int limit = mLayout.getScrollLimit();
-            if (oldX > 0 && newX == 0 || oldX < limit && newX == limit) {
-                float v = mScroller.getCurrVelocity();
-                if (newX == limit) v = -v;
-
-                // I don't know why, but getCurrVelocity() can return NaN.
-                if (!Float.isNaN(v)) {
-                    mPaper.edgeReached(v);
-                }
-            }
-            paperActive = mPaper.advanceAnimation();
-        }
-
-        more |= paperActive;
-
         if (mAnimation != null) {
             more |= mAnimation.calculate(animTime);
         }
@@ -278,7 +262,7 @@
                 mLayout.mVisibleEnd - mLayout.mVisibleStart);
 
         for (int i = mLayout.mVisibleEnd - 1; i >= mLayout.mVisibleStart; --i) {
-            int r = renderItem(canvas, i, 0, paperActive);
+            int r = renderItem(canvas, i, 0);
             if ((r & RENDER_MORE_FRAME) != 0) more = true;
             if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i;
         }
@@ -286,8 +270,7 @@
         for (int pass = 1; requestCount != 0; ++pass) {
             int newCount = 0;
             for (int i = 0; i < requestCount; ++i) {
-                int r = renderItem(canvas,
-                        requestedSlot[i], pass, paperActive);
+                int r = renderItem(canvas, requestedSlot[i], pass);
                 if ((r & RENDER_MORE_FRAME) != 0) more = true;
                 if ((r & RENDER_MORE_PASS) != 0) requestedSlot[newCount++] = i;
             }
@@ -310,15 +293,10 @@
         mMoreAnimation = more;
     }
 
-    private int renderItem(
-            GLCanvas canvas, int index, int pass, boolean paperActive) {
+    private int renderItem(GLCanvas canvas, int index, int pass) {
         canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
         Rect rect = mLayout.getSlotRect(index, mTempRect);
-        if (paperActive) {
-            canvas.multiplyMatrix(mPaper.getTransform(rect, mScrollX), 0);
-        } else {
-            canvas.translate(rect.left, rect.top, 0);
-        }
+        canvas.translate(rect.left, rect.top, 0);
         if (mAnimation != null && mAnimation.isActive()) {
             mAnimation.apply(canvas, index, rect);
         }
@@ -390,6 +368,9 @@
         public int rowsLand = -1;
         public int rowsPort = -1;
         public int slotGap = -1;
+        public int slotGapLand = -1;
+        public int colsLand = -1;
+        public int colsPort = -1;
     }
 
     public class Layout {
@@ -437,9 +418,19 @@
             if (WIDE) {
                 col = index / mUnitCount;
                 row = index - col * mUnitCount;
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    // If RTL, recalculate the columns.
+                    col = mUnitCount - (index - row * mUnitCount) - 1;
+                }
             } else {
                 row = index / mUnitCount;
                 col = index - row * mUnitCount;
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    // If RTL, recalculate the columns.
+                    col = mUnitCount - (index - row * mUnitCount) - 1;
+                }
             }
 
             int x = mHorizontalPadding.get() + col * (mSlotWidth + mSlotGap);
@@ -480,7 +471,7 @@
             int availableUnits = Math.min(mUnitCount, mSlotCount);
             int usedMinorLength = availableUnits * minorUnitSize +
                     (availableUnits - 1) * mSlotGap;
-            padding[0] = (minorLength - usedMinorLength) / 2;
+            padding[0] = 0;//mActivity.getResources().getDimensionPixelSize(R.dimen.toolbar_height);
 
             // Then calculate how many columns we need for all slots.
             int count = ((mSlotCount + mUnitCount - 1) / mUnitCount);
@@ -488,20 +479,20 @@
 
             // If the content length is less then the screen width, put
             // extra padding in left and right.
-            padding[1] = Math.max(0, (majorLength - mContentLength) / 2);
+            padding[1] = 0 ;//Math.max(0, (majorLength - mContentLength) / 2);
         }
 
         private void initLayoutParameters() {
             // Initialize mSlotWidth and mSlotHeight from mSpec
             if (mSpec.slotWidth != -1) {
-                mSlotGap = 0;
-                mSlotWidth = mSpec.slotWidth;
-                mSlotHeight = mSpec.slotHeight;
+                mSlotGap = (mWidth > mHeight) ? mSpec.slotGapLand : mSpec.slotGap;
+                int cols = (mWidth > mHeight) ? mSpec.colsLand : mSpec.colsPort;
+                mSlotHeight = Math.max(1, (mWidth - (cols - 1) * mSlotGap) / cols) ;
+                mSlotWidth = mSlotHeight ;//mSpec.slotWidth;
             } else {
-                int rows = (mWidth > mHeight) ? mSpec.rowsLand : mSpec.rowsPort;
-                mSlotGap = mSpec.slotGap;
-                mSlotHeight = Math.max(1, (mHeight - (rows - 1) * mSlotGap) / rows);
-                mSlotWidth = mSlotHeight - mSpec.slotHeightAdditional;
+                mSlotGap = (mWidth > mHeight) ? mSpec.slotGapLand : mSpec.slotGap;;
+                mSlotHeight = mSpec.slotHeight;//Math.max(1, (mHeight - (rows - 1) * mSlotGap) / rows);
+                mSlotWidth = mWidth;//mSlotHeight - mSpec.slotHeightAdditional;
             }
 
             if (mRenderer != null) {
@@ -531,6 +522,13 @@
             int position = mScrollPosition;
 
             if (WIDE) {
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    // If RTL, recalculate the position.
+                    position = mContentLength > mWidth ? (mContentLength - position - mWidth)
+                            : position;
+                    position = Math.max(0, position);
+                }
                 int startCol = position / (mSlotWidth + mSlotGap);
                 int start = Math.max(0, mUnitCount * startCol);
                 int endCol = (position + mWidth + mSlotWidth + mSlotGap - 1) /
@@ -577,7 +575,6 @@
         public int getSlotIndexByPosition(float x, float y) {
             int absoluteX = Math.round(x) + (WIDE ? mScrollPosition : 0);
             int absoluteY = Math.round(y) + (WIDE ? 0 : mScrollPosition);
-
             absoluteX -= mHorizontalPadding.get();
             absoluteY -= mVerticalPadding.get();
 
@@ -587,6 +584,15 @@
 
             int columnIdx = absoluteX / (mSlotWidth + mSlotGap);
             int rowIdx = absoluteY / (mSlotHeight + mSlotGap);
+            if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                    .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                // If RTL, recalculate the columnIdx/rowIdx.
+                if (WIDE) {
+                    rowIdx = mUnitCount - rowIdx - 1;
+                } else {
+                    columnIdx = mUnitCount - columnIdx - 1;
+                }
+            }
 
             if (!WIDE && columnIdx >= mUnitCount) {
                 return INDEX_NONE;
@@ -674,9 +680,6 @@
             float distance = WIDE ? distanceX : distanceY;
             int overDistance = mScroller.startScroll(
                     Math.round(distance), 0, mLayout.getScrollLimit());
-            if (mOverscrollEffect == OVERSCROLL_3D && overDistance != 0) {
-                mPaper.overScroll(overDistance);
-            }
             invalidate();
             return true;
         }
@@ -785,4 +788,11 @@
             if (progress == 1f) mEnabled = false;
         }
     }
+
+    /**
+     * Get the SlotView's max scroll value.
+     */
+    public int getScrollLimit() {
+        return mLayout.getScrollLimit();
+    }
 }
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java
index 36500a0..5c3df5f 100644
--- a/src/com/android/gallery3d/ui/TileImageView.java
+++ b/src/com/android/gallery3d/ui/TileImageView.java
@@ -90,7 +90,6 @@
     private int mOffsetX;
     private int mOffsetY;
 
-    private int mUploadQuota;
     private boolean mRenderComplete;
 
     private final RectF mSourceRect = new RectF();
@@ -155,9 +154,10 @@
         mTileDecoder = mThreadPool.submit(new TileDecoder());
         if (sTileSize == 0) {
             if (isHighResolution(context.getAndroidContext())) {
-                sTileSize = 512 ;
+                // Need to tuning
+                sTileSize = 2048;
             } else {
-                sTileSize = 256;
+                sTileSize = 1024;
             }
         }
     }
@@ -185,7 +185,6 @@
             mLevelCount = mModel.getLevelCount();
         }
         layoutTiles(mCenterX, mCenterY, mScale, mRotation);
-        invalidate();
     }
 
     @Override
@@ -359,7 +358,6 @@
         mScale = scale;
         mRotation = rotation;
         layoutTiles(centerX, centerY, scale, rotation);
-        invalidate();
         return true;
     }
 
@@ -368,7 +366,6 @@
 
         if (mTileDecoder != null) {
             mTileDecoder.cancel();
-            mTileDecoder.get();
             mTileDecoder = null;
         }
 
@@ -405,7 +402,6 @@
 
     @Override
     protected void render(GLCanvas canvas) {
-        mUploadQuota = UPLOAD_LIMIT;
         mRenderComplete = true;
 
         int level = mLevel;
@@ -473,10 +469,14 @@
     }
 
     void queueForUpload(Tile tile) {
+        // if getGLRoot retun null, then maybe no place to show
+        // these decode tiles.
+        if (getGLRoot() == null)
+            return;
         synchronized (this) {
             mUploadQueue.push(tile);
         }
-        if (mTileUploader.mActive.compareAndSet(false, true)) {
+        if (getGLRoot() != null && mTileUploader.mActive.compareAndSet(false, true)) {
             getGLRoot().addOnGLIdleListener(mTileUploader);
         }
     }
@@ -560,13 +560,11 @@
         AtomicBoolean mActive = new AtomicBoolean(false);
 
         @Override
-        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) {
-            // Skips uploading if there is a pending rendering request.
-            // Returns true to keep uploading in next rendering loop.
-            if (renderRequested) return true;
-            int quota = UPLOAD_LIMIT;
+        public boolean onGLIdle(GLCanvas canvas, boolean renderRequested, long dueTime) {
+            long now = System.nanoTime();
+            long uploadTime = 0;
             Tile tile = null;
-            while (quota > 0) {
+            while (now + uploadTime < dueTime) {
                 synchronized (TileImageView.this) {
                     tile = mUploadQueue.pop();
                 }
@@ -576,8 +574,10 @@
                     Utils.assertTrue(tile.mTileState == STATE_DECODED);
                     tile.updateContent(canvas);
                     if (!hasBeenLoaded) tile.draw(canvas, 0, 0);
-                    --quota;
                 }
+                long t1 = System.nanoTime();
+                uploadTime = t1 - now;
+                now = t1;
             }
             if (tile == null) mActive.set(false);
             return tile != null;
@@ -597,13 +597,8 @@
         if (tile != null) {
             if (!tile.isContentValid()) {
                 if (tile.mTileState == STATE_DECODED) {
-                    if (mUploadQuota > 0) {
-                        --mUploadQuota;
-                        tile.updateContent(canvas);
-                    } else {
-                        mRenderComplete = false;
-                    }
-                } else if (tile.mTileState != STATE_DECODE_FAIL){
+                    mRenderComplete = false;
+                } else if (tile.mTileState != STATE_DECODE_FAIL) {
                     mRenderComplete = false;
                     queueForDecode(tile);
                 }
diff --git a/src/com/android/gallery3d/ui/TiledScreenNail.java b/src/com/android/gallery3d/ui/TiledScreenNail.java
index 860e230..9b24eab 100644
--- a/src/com/android/gallery3d/ui/TiledScreenNail.java
+++ b/src/com/android/gallery3d/ui/TiledScreenNail.java
@@ -153,7 +153,7 @@
 
     @Override
     public void draw(GLCanvas canvas, int x, int y, int width, int height) {
-        if (mTexture == null || !mTexture.isReady()) {
+        if (mTexture == null) {
             if (mAnimationStartTime == ANIMATION_NOT_NEEDED) {
                 mAnimationStartTime = ANIMATION_NEEDED;
             }
@@ -177,7 +177,7 @@
 
     @Override
     public void draw(GLCanvas canvas, RectF source, RectF dest) {
-        if (mTexture == null || !mTexture.isReady()) {
+        if (mTexture == null) {
             canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(),
                     mPlaceholderColor);
             return;
@@ -213,6 +213,6 @@
     }
 
     public static void setMaxSide(int size) {
-        sMaxSide = size;
+        sMaxSide = Math.max(size, sMaxSide);
     }
 }
diff --git a/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
new file mode 100644
index 0000000..d37d4e8
--- /dev/null
+++ b/src/com/android/gallery3d/ui/TimeLineSlidingWindow.java
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.ui;
+
+import android.graphics.Bitmap;
+import android.os.Message;
+
+import com.android.gallery3d.app.AbstractGalleryActivity;
+import com.android.gallery3d.app.TimeLineDataLoader;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.data.TimeLineTitleMediaItem;
+import com.android.gallery3d.glrenderer.Texture;
+import com.android.gallery3d.glrenderer.TiledTexture;
+import com.android.gallery3d.util.Future;
+import com.android.gallery3d.util.FutureListener;
+import com.android.gallery3d.util.JobLimiter;
+
+public class TimeLineSlidingWindow implements TimeLineDataLoader.DataListener {
+    @SuppressWarnings("unused")
+    private static final String TAG = "TimeLineSlidingWindow";
+
+    private static final int MSG_UPDATE_ENTRY = 0;
+    private static final int JOB_LIMIT = 2;
+
+    public interface Listener {
+        void onSizeChanged(int[] size);
+        void onContentChanged();
+    }
+
+    public static class AlbumEntry {
+        public MediaItem item;
+        public Path path;
+        public boolean isPanorama;
+        public int rotation;
+        public int mediaType;
+        public boolean isWaitDisplayed;
+        public TiledTexture bitmapTexture;
+        public Texture content;
+        private BitmapLoader contentLoader;
+
+    }
+
+    private final TimeLineDataLoader mSource;
+    private final AlbumEntry mData[];
+    private final SynchronizedHandler mHandler;
+    private final JobLimiter mThreadPool;
+    private final TiledTexture.Uploader mTileUploader;
+
+    private int mSize;
+    private int mSlotWidth;
+    private int mContentStart = 0;
+    private int mContentEnd = 0;
+    private int mActiveStart = 0;
+    private int mActiveEnd = 0;
+    private Listener mListener;
+    private int mActiveRequestCount = 0;
+    private boolean mIsActive = false;
+
+    private final TimeLineTitleMaker mTitleMaker;
+
+    public TimeLineSlidingWindow(AbstractGalleryActivity activity, TimeLineDataLoader source,
+            int cacheSize, TimeLineSlotRenderer.LabelSpec labelSpec, TimeLineSlotView slotView) {
+        source.setDataListener(this);
+        mSource = source;
+        mData = new AlbumEntry[cacheSize];
+        mSize = source.size();
+        mHandler = new SynchronizedHandler(activity.getGLRoot()) {
+            @Override
+            public void handleMessage(Message message) {
+                Utils.assertTrue(message.what == MSG_UPDATE_ENTRY);
+                ((ThumbnailLoader) message.obj).updateEntry();
+            }
+        };
+
+        mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT);
+        mTileUploader = new TiledTexture.Uploader(activity.getGLRoot());
+        mTitleMaker = new TimeLineTitleMaker(activity.getAndroidContext(), labelSpec, slotView);
+    }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    public AlbumEntry get(int slotIndex) {
+        if (!isActiveSlot(slotIndex)) {
+            return null;
+        }
+        return mData[slotIndex % mData.length];
+    }
+
+    private boolean isActiveSlot(int slotIndex) {
+        return slotIndex >= mActiveStart && slotIndex < mActiveEnd;
+    }
+
+    private void setContentWindow(int contentStart, int contentEnd) {
+        if (contentStart == mContentStart && contentEnd == mContentEnd) return;
+
+        if (!mIsActive) {
+            mContentStart = contentStart;
+            mContentEnd = contentEnd;
+            mSource.setActiveWindow(contentStart, contentEnd);
+            return;
+        }
+
+        if (contentStart >= mContentEnd || mContentStart >= contentEnd) {
+            for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
+                freeSlotContent(i);
+            }
+            mSource.setActiveWindow(contentStart, contentEnd);
+            for (int i = contentStart; i < contentEnd; ++i) {
+                prepareSlotContent(i);
+            }
+        } else {
+            for (int i = mContentStart; i < contentStart; ++i) {
+                freeSlotContent(i);
+            }
+            for (int i = contentEnd, n = mContentEnd; i < n; ++i) {
+                freeSlotContent(i);
+            }
+            mSource.setActiveWindow(contentStart, contentEnd);
+            for (int i = contentStart, n = mContentStart; i < n; ++i) {
+                prepareSlotContent(i);
+            }
+            for (int i = mContentEnd; i < contentEnd; ++i) {
+                prepareSlotContent(i);
+            }
+        }
+
+        mContentStart = contentStart;
+        mContentEnd = contentEnd;
+    }
+
+    public void setActiveWindow(int start, int end) {
+        if (!(start <= end && end - start <= mData.length)) {
+            Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize);
+        }
+        AlbumEntry data[] = mData;
+
+        mActiveStart = start;
+        mActiveEnd = end;
+
+        int contentStart = Utils.clamp((start + end) / 2 - data.length / 2,
+                0, Math.max(0, mSize - data.length));
+        int contentEnd = Math.min(contentStart + data.length, mSize);
+        setContentWindow(contentStart, contentEnd);
+        updateTextureUploadQueue();
+        if (mIsActive) updateAllImageRequests();
+    }
+
+    private void uploadBgTextureInSlot(int index) {
+        if (index < mContentEnd && index >= mContentStart) {
+            AlbumEntry entry = mData[index % mData.length];
+            if (entry == null) return;
+            if (entry.bitmapTexture != null) {
+                mTileUploader.addTexture(entry.bitmapTexture);
+            }
+        }
+    }
+
+    private void updateTextureUploadQueue() {
+        if (!mIsActive) return;
+        mTileUploader.clear();
+
+        // add foreground textures
+        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
+            AlbumEntry entry = mData[i % mData.length];
+            if (entry == null) {
+                continue;
+            }
+            if (entry.bitmapTexture != null) {
+                mTileUploader.addTexture(entry.bitmapTexture);
+            }
+        }
+
+        // add background textures
+        int range = Math.max(
+                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
+        for (int i = 0; i < range; ++i) {
+            uploadBgTextureInSlot(mActiveEnd + i);
+            uploadBgTextureInSlot(mActiveStart - i - 1);
+        }
+    }
+
+    // We would like to request non active slots in the following order:
+    // Order:    8 6 4 2                   1 3 5 7
+    //         |---------|---------------|---------|
+    //                   |<-  active  ->|
+    //         |<-------- cached range ----------->|
+    private void requestNonactiveImages() {
+        int range = Math.max(
+                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
+        for (int i = 0; i < range; ++i) {
+            requestSlotImage(mActiveEnd + i);
+            requestSlotImage(mActiveStart - 1 - i);
+        }
+    }
+
+    // return whether the request is in progress or not
+    private boolean requestSlotImage(int slotIndex) {
+        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false;
+        AlbumEntry entry = mData[slotIndex % mData.length];
+        if (entry == null || entry.item == null) return false;
+
+        entry.contentLoader.startLoad();
+        return entry.contentLoader.isRequestInProgress();
+    }
+
+    private void cancelNonactiveImages() {
+        int range = Math.max(
+                (mContentEnd - mActiveEnd), (mActiveStart - mContentStart));
+        for (int i = 0; i < range; ++i) {
+            cancelSlotImage(mActiveEnd + i);
+            cancelSlotImage(mActiveStart - 1 - i);
+        }
+    }
+
+    private void cancelSlotImage(int slotIndex) {
+        if (slotIndex < mContentStart || slotIndex >= mContentEnd) return;
+        AlbumEntry item = mData[slotIndex % mData.length];
+        if (item == null) return;
+        if (item.contentLoader != null) item.contentLoader.cancelLoad();
+    }
+
+    private void freeSlotContent(int slotIndex) {
+        AlbumEntry data[] = mData;
+        int index = slotIndex % data.length;
+        AlbumEntry entry = data[index];
+        if (entry != null) {
+            if (entry.contentLoader != null) entry.contentLoader.recycle();
+            if (entry.bitmapTexture != null) entry.bitmapTexture.recycle();
+        }
+        data[index] = null;
+    }
+
+
+    private void prepareSlotContent(int slotIndex) {
+        AlbumEntry entry = new AlbumEntry();
+        MediaItem item = mSource.get(slotIndex); // item could be null;
+        entry.item = item;
+        entry.mediaType = (item == null)
+                ? MediaItem.MEDIA_TYPE_UNKNOWN
+                : entry.item.getMediaType();
+        entry.path = (item == null) ? null : item.getPath();
+        entry.rotation = (item == null) ? 0 : item.getRotation();
+        entry.contentLoader = new ThumbnailLoader(slotIndex, entry.item);
+        mData[slotIndex % mData.length] = entry;
+    }
+
+    private void updateAllTimelineTitleContent(boolean needRequest) {
+        for (int slotIndex = mContentStart, n = mContentEnd; slotIndex < n; ++slotIndex) {
+            AlbumEntry entry = mData[slotIndex % mData.length];
+            if (entry == null) {
+                continue;
+            }
+            if (entry.mediaType == MediaItem.MEDIA_TYPE_TIMELINE_TITLE) {
+                freeSlotContent(slotIndex);
+                prepareSlotContent(slotIndex);
+                if (needRequest) {
+                    requestSlotImage(slotIndex);
+                }
+            }
+        }
+    }
+
+    private void updateAllImageRequests() {
+        mActiveRequestCount = 0;
+        for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) {
+            if (requestSlotImage(i)) ++mActiveRequestCount;
+        }
+        if (mActiveRequestCount == 0) {
+            requestNonactiveImages();
+        } else {
+            cancelNonactiveImages();
+        }
+    }
+
+    private class ThumbnailLoader extends BitmapLoader {
+        private final int mSlotIndex;
+        private final MediaItem mItem;
+
+        public ThumbnailLoader(int slotIndex, MediaItem item) {
+            mSlotIndex = slotIndex;
+            mItem = item;
+        }
+
+        @Override
+        protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) {
+            if (mItem.getMediaType() != MediaObject.MEDIA_TYPE_TIMELINE_TITLE) {
+                return mThreadPool.submit(
+                        mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this);
+            } else if( mItem.getMediaType() == MediaObject.MEDIA_TYPE_TIMELINE_TITLE ){
+                return mThreadPool.submit(
+                        ((TimeLineTitleMediaItem) mItem).requestTitle(
+                                MediaItem.TYPE_MICROTHUMBNAIL, mTitleMaker), this);
+            }
+            return null;
+        }
+
+        @Override
+        protected void onLoadComplete(Bitmap bitmap) {
+            mHandler.obtainMessage(MSG_UPDATE_ENTRY, this).sendToTarget();
+        }
+
+        public void updateEntry() {
+            Bitmap bitmap = getBitmap();
+            if (bitmap == null) return; // error or recycled
+
+                AlbumEntry entry = mData[mSlotIndex % mData.length];
+                if (entry == null)  return;
+                entry.bitmapTexture = new TiledTexture(bitmap);
+                entry.content = entry.bitmapTexture;
+
+                if (isActiveSlot(mSlotIndex)) {
+                    mTileUploader.addTexture(entry.bitmapTexture);
+                    --mActiveRequestCount;
+                    if (mActiveRequestCount == 0) requestNonactiveImages();
+                    if (mListener != null) mListener.onContentChanged();
+                } else {
+                    mTileUploader.addTexture(entry.bitmapTexture);
+                }
+
+        }
+    }
+
+    @Override
+    public void onSizeChanged() {
+        int size = mSource.size();
+        if (mSize != size) {
+            mSize = size;
+            if (mListener != null) mListener.onSizeChanged(mSource.getSubMediaSetCount());
+            if (mContentEnd > mSize) mContentEnd = mSize;
+            if (mActiveEnd > mSize) mActiveEnd = mSize;
+        }
+    }
+
+    @Override
+    public void onContentChanged(int index) {
+        if (index >= mContentStart && index < mContentEnd && mIsActive) {
+            freeSlotContent(index);
+            prepareSlotContent(index);
+            updateAllImageRequests();
+            updateTextureUploadQueue();
+            if (mListener != null && isActiveSlot(index)) {
+                mListener.onContentChanged();
+            }
+        }
+    }
+
+    public void resume() {
+        mIsActive = true;
+        TiledTexture.prepareResources();
+        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
+            prepareSlotContent(i);
+        }
+        updateAllImageRequests();
+    }
+
+    public void pause() {
+        mIsActive = false;
+        mTileUploader.clear();
+        TiledTexture.freeResources();
+        for (int i = mContentStart, n = mContentEnd; i < n; ++i) {
+            freeSlotContent(i);
+        }
+    }
+
+    public void onSlotSizeChanged(int width, int height) {
+        if (mSlotWidth == width) {
+            updateAllTimelineTitleContent(true);
+            return;
+        }
+
+        mSlotWidth = width;
+
+        if (!mIsActive) return;
+        updateAllTimelineTitleContent(false);
+        updateAllImageRequests();
+        updateTextureUploadQueue();
+    }
+}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
new file mode 100644
index 0000000..575b9d6
--- /dev/null
+++ b/src/com/android/gallery3d/ui/TimeLineSlotRenderer.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.gallery3d.ui;
+
+
+import com.android.gallery3d.app.AbstractGalleryActivity;
+import com.android.gallery3d.app.TimeLineDataLoader;
+import com.android.gallery3d.data.MediaItem;
+import com.android.gallery3d.data.MediaObject;
+import com.android.gallery3d.data.Path;
+import com.android.gallery3d.glrenderer.ColorTexture;
+import com.android.gallery3d.glrenderer.GLCanvas;
+import com.android.gallery3d.glrenderer.Texture;
+import com.android.gallery3d.glrenderer.TiledTexture;
+
+public class TimeLineSlotRenderer extends AbstractSlotRenderer {
+
+    @SuppressWarnings("unused")
+    private static final String TAG = "AlbumView";
+
+    private final int mPlaceholderColor;
+    private static final int CACHE_SIZE = 96;
+
+    private TimeLineSlidingWindow mDataWindow;
+    private final AbstractGalleryActivity mActivity;
+    private final ColorTexture mWaitLoadingTexture;
+    private final TimeLineSlotView mSlotView;
+    private final SelectionManager mSelectionManager;
+
+    private int mPressedIndex = -1;
+    private boolean mAnimatePressedUp;
+    private Path mHighlightItemPath = null;
+    private boolean mInSelectionMode;
+
+    private AlbumSlotRenderer.SlotFilter mSlotFilter;
+    private final LabelSpec mLabelSpec;
+
+    public static class LabelSpec {
+
+        public int timeLineTitleHeight;
+        public int timeLineTitleFontSize;
+        public int timeLineTitleTextColor;
+        public int timeLineNumberTextColor;
+        public int timeLineTitleBackgroundColor;
+}
+    public TimeLineSlotRenderer(AbstractGalleryActivity activity, TimeLineSlotView slotView,
+                                    SelectionManager selectionManager, LabelSpec labelSpec,
+                                    int placeholderColor) {
+        super(activity);
+        mActivity = activity;
+        mSlotView = slotView;
+        mLabelSpec = labelSpec;
+        mSelectionManager = selectionManager;
+        mPlaceholderColor = placeholderColor;
+        mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
+        mWaitLoadingTexture.setSize(1, 1);
+
+    }
+
+    public void setPressedIndex(int index) {
+        if (mPressedIndex == index) return;
+        mPressedIndex = index;
+        mSlotView.invalidate();
+    }
+
+    public void setPressedUp() {
+        if (mPressedIndex == -1) return;
+        mAnimatePressedUp = true;
+        mSlotView.invalidate();
+    }
+
+    public void setHighlightItemPath(Path path) {
+        if (mHighlightItemPath == path) return;
+        mHighlightItemPath = path;
+        mSlotView.invalidate();
+    }
+
+    protected static Texture checkContentTexture(Texture texture) {
+        return (texture instanceof TiledTexture)
+                && !((TiledTexture) texture).isReady()
+                ? null
+                : texture;
+    }
+
+    protected int renderOverlay(GLCanvas canvas, int index,
+            TimeLineSlidingWindow.AlbumEntry entry, int width, int height) {
+        int renderRequestFlags = 0;
+        if (mPressedIndex == index) {
+            if (mAnimatePressedUp) {
+                drawPressedUpFrame(canvas, width, height);
+                renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
+                if (isPressedUpFrameFinished()) {
+                    mAnimatePressedUp = false;
+                    mPressedIndex = -1;
+                }
+            } else {
+                drawPressedFrame(canvas, width, height);
+            }
+        } else if ((entry.path != null) && (mHighlightItemPath == entry.path)) {
+            drawSelectedFrame(canvas, width, height);
+        } else if (mInSelectionMode && entry.mediaType != MediaItem.MEDIA_TYPE_TIMELINE_TITLE
+                && mSelectionManager.isItemSelected(entry.path)) {
+            drawSelectedFrame(canvas, width, height);
+        }
+        return renderRequestFlags;
+    }
+
+    protected class MyDataModelListener implements TimeLineSlidingWindow.Listener {
+        @Override
+        public void onContentChanged() {
+            mSlotView.invalidate();
+        }
+
+        @Override
+        public void onSizeChanged(int[] size) {
+            mSlotView.setSlotCount(size);
+            mSlotView.invalidate();
+        }
+    }
+
+    public void resume() {
+        mDataWindow.resume();
+    }
+
+    public void pause() {
+        mDataWindow.pause();
+    }
+
+    @Override
+    public void prepareDrawing() {
+        mInSelectionMode = mSelectionManager.inSelectionMode();
+    }
+
+    @Override
+    public void onVisibleRangeChanged(int visibleStart, int visibleEnd) {
+        if (mDataWindow != null) {
+            mDataWindow.setActiveWindow(visibleStart, visibleEnd);
+        }
+    }
+
+    @Override
+    public void onSlotSizeChanged(int width, int height) {
+        if (mDataWindow != null) {
+            mDataWindow.onSlotSizeChanged(width, height);
+        }
+    }
+
+    public void setSlotFilter(AlbumSlotRenderer.SlotFilter slotFilter) {
+        mSlotFilter = slotFilter;
+    }
+
+    public void setModel(TimeLineDataLoader model) {
+        if (mDataWindow != null) {
+            mDataWindow.setListener(null);
+            mDataWindow = null;
+        }
+        if (model != null) {
+            mDataWindow = new TimeLineSlidingWindow(mActivity, model, CACHE_SIZE, mLabelSpec,
+                    mSlotView);
+            mDataWindow.setListener(new MyDataModelListener());
+        }
+    }
+
+    @Override
+    public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) {
+        if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0;
+
+        TimeLineSlidingWindow.AlbumEntry entry = mDataWindow.get(index);
+        int renderRequestFlags = 0;
+        if (entry != null) {
+            Texture content = checkContentTexture(entry.content);
+            if (content == null) {
+                content = mWaitLoadingTexture;
+                entry.isWaitDisplayed = true;
+            } else if (entry.isWaitDisplayed) {
+                entry.isWaitDisplayed = false;
+            }
+            drawContent(canvas, content, width, height, entry.rotation);
+
+            if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
+                drawVideoOverlay(canvas, width, height, true, 0);
+            }
+
+            renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);
+        }
+        return renderRequestFlags;
+    }
+}
diff --git a/src/com/android/gallery3d/ui/TimeLineSlotView.java b/src/com/android/gallery3d/ui/TimeLineSlotView.java
new file mode 100755
index 0000000..26f5c7f
--- /dev/null
+++ b/src/com/android/gallery3d/ui/TimeLineSlotView.java
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gallery3d.ui;
+
+import android.graphics.Rect;
+import android.text.TextUtils;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+
+import com.android.gallery3d.anim.Animation;
+import com.android.gallery3d.app.AbstractGalleryActivity;
+import com.android.gallery3d.common.ApiHelper.SystemProperties;
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.glrenderer.GLCanvas;
+
+import java.util.Locale;
+
+public class TimeLineSlotView extends GLView {
+    @SuppressWarnings("unused")
+    private static final String TAG = "TimeLineSlotView";
+
+    public static final int INDEX_NONE = -1;
+    private static final int mainKey = SystemProperties.getInt("qemu.hw.mainkeys", 1);
+
+    public static final int RENDER_MORE_PASS = 1;
+    public static final int RENDER_MORE_FRAME = 2;
+
+    private int mWidth  = 0;
+
+    public interface Listener {
+        public void onDown(int index);
+        public void onUp(boolean followedByLongPress);
+        public void onSingleTapUp(int index, boolean isTitle);
+        public void onLongTap(int index, boolean isTitle);
+        public void onScrollPositionChanged(int position, int total);
+    }
+
+    public static class SimpleListener implements Listener {
+        @Override public void onDown(int index) {}
+        @Override public void onUp(boolean followedByLongPress) {}
+        @Override public void onSingleTapUp(int index, boolean isTitle) {}
+        @Override public void onLongTap(int index, boolean isTitle) {}
+        @Override public void onScrollPositionChanged(int position, int total) {}
+    }
+
+    private final GestureDetector mGestureDetector;
+    private final ScrollerHelper mScroller;
+
+    private Listener mListener;
+    private SlotAnimation mAnimation = null;
+    private final Layout mLayout = new Layout();
+    private int mStartIndex = INDEX_NONE;
+
+    // whether the down action happened while the view is scrolling.
+    private boolean mDownInScrolling;
+
+    private TimeLineSlotRenderer mRenderer;
+
+    private int[] mRequestRenderSlots = new int[16];
+
+    // Flag to check whether it is come from Photo Page.
+    private boolean isFromPhotoPage = false;
+
+    public TimeLineSlotView(AbstractGalleryActivity activity, Spec spec) {
+        mGestureDetector = new GestureDetector(activity, new MyGestureListener());
+        mScroller = new ScrollerHelper(activity);
+        setSlotSpec(spec);
+    }
+
+    public void setSlotRenderer(TimeLineSlotRenderer slotDrawer) {
+        mRenderer = slotDrawer;
+        if (mRenderer != null) {
+            mRenderer.onVisibleRangeChanged(getVisibleStart(), getVisibleEnd());
+        }
+    }
+
+    public void setCenterIndex(int index) {
+        int size = mLayout.getSlotSize();
+        if (index < 0 || index >= size) {
+            return;
+        }
+        Rect rect = mLayout.getSlotRect(index);
+        if (rect != null) {
+            int position = (rect.top + rect.bottom - getHeight()) / 2;
+            setScrollPosition(position);
+        }
+    }
+
+    public void makeSlotVisible(int index) {
+        Rect rect = mLayout.getSlotRect(index);
+        if (rect == null) return;
+        int visibleBegin = mScrollY;
+        int visibleLength = getHeight();
+        int visibleEnd = visibleBegin + visibleLength;
+        int slotBegin = rect.top;
+        int slotEnd = rect.bottom;
+
+        int position = visibleBegin;
+        if (visibleLength < slotEnd - slotBegin) {
+            position = visibleBegin;
+        } else if (slotBegin < visibleBegin) {
+            position = slotBegin;
+        } else if (slotEnd > visibleEnd && mainKey == 1) {
+            position = slotEnd - visibleLength;
+        } else if (slotBegin > visibleEnd && mainKey == 0) {
+            position = slotBegin - visibleLength;
+        }
+
+        setScrollPosition(position);
+    }
+
+    /**
+     * Set the flag which used for check whether it is come from Photo Page.
+     */
+    public void setIsFromPhotoPage(boolean flag) {
+        isFromPhotoPage = flag;
+    }
+
+    public void setScrollPosition(int position) {
+        position = Utils.clamp(position, 0, mLayout.getScrollLimit());
+        mScroller.setPosition(position);
+        updateScrollPosition(position, false);
+    }
+
+    public void setSlotSpec(Spec spec) {
+        mLayout.setSlotSpec(spec);
+    }
+
+    @Override
+    protected void onLayout(boolean changeSize, int l, int t, int r, int b) {
+        if (!changeSize) return;
+        mWidth = r - l;
+
+        // Make sure we are still at a reasonable scroll position after the size
+        // is changed (like orientation change). We choose to keep the center
+        // visible slot still visible. This is arbitrary but reasonable.
+        int visibleIndex =
+                (mLayout.getVisibleStart() + mLayout.getVisibleEnd()) / 2;
+        mLayout.setSize(r - l, b - t);
+        makeSlotVisible(visibleIndex);
+    }
+
+    public void startScatteringAnimation(RelativePosition position) {
+        mAnimation = new ScatteringAnimation(position);
+        mAnimation.start();
+        if (mLayout.getSlotSize() != 0) invalidate();
+    }
+
+    public void startRisingAnimation() {
+        mAnimation = new RisingAnimation();
+        mAnimation.start();
+        if (mLayout.getSlotSize() != 0) invalidate();
+    }
+
+    private void updateScrollPosition(int position, boolean force) {
+        if (!force && (position == mScrollY)) return;
+        mScrollY = position;
+        mLayout.setScrollPosition(position);
+        onScrollPositionChanged(position);
+    }
+
+    protected void onScrollPositionChanged(int newPosition) {
+        int limit = mLayout.getScrollLimit();
+        mListener.onScrollPositionChanged(newPosition, limit);
+    }
+
+    public Rect getSlotRect(int slotIndex) {
+        return mLayout.getSlotRect(slotIndex);
+    }
+
+    @Override
+    protected boolean onTouch(MotionEvent event) {
+        mGestureDetector.onTouchEvent(event);
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                mDownInScrolling = !mScroller.isFinished();
+                mScroller.forceFinished();
+                break;
+            case MotionEvent.ACTION_UP:
+                invalidate();
+                break;
+        }
+        return true;
+    }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    private static int[] expandIntArray(int array[], int capacity) {
+        while (array.length < capacity) {
+            array = new int[array.length * 2];
+        }
+        return array;
+    }
+
+    @Override
+    protected void render(GLCanvas canvas) {
+        super.render(canvas);
+
+        if (mRenderer == null) return;
+        mRenderer.prepareDrawing();
+
+        long animTime = AnimationTime.get();
+        boolean more = mScroller.advanceAnimation(animTime);
+        int oldX = mScrollX;
+        updateScrollPosition(mScroller.getPosition(), false);
+
+        if (mAnimation != null) {
+            more |= mAnimation.calculate(animTime);
+        }
+
+        canvas.translate(-mScrollX, -mScrollY);
+
+        int requestCount = 0;
+        int requestedSlot[] = expandIntArray(mRequestRenderSlots,
+                mLayout.getVisibleEnd() - mLayout.getVisibleStart());
+
+        for (int i = mLayout.getVisibleEnd() - 1; i >= mLayout.getVisibleStart(); --i) {
+            int r = renderItem(canvas, i, 0);
+            if ((r & RENDER_MORE_FRAME) != 0) more = true;
+            if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i;
+        }
+
+        for (int pass = 1; requestCount != 0; ++pass) {
+            int newCount = 0;
+            for (int i = 0; i < requestCount; ++i) {
+                int r = renderItem(canvas, requestedSlot[i], pass);
+                if ((r & RENDER_MORE_FRAME) != 0) more = false;
+                if ((r & RENDER_MORE_PASS) != 0) requestedSlot[newCount++] = i;
+            }
+            requestCount = newCount;
+        }
+
+        canvas.translate(mScrollX, mScrollY);
+
+        if (more) invalidate();
+
+    }
+
+    private int renderItem(GLCanvas canvas, int index, int pass) {
+        Rect rect = mLayout.getSlotRect(index);
+        if (rect == null) return 0;
+        canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX);
+        canvas.translate(rect.left, rect.top, 0);
+        if (mAnimation != null && mAnimation.isActive()) {
+            mAnimation.apply(canvas, index, rect);
+        }
+        int result = mRenderer.renderSlot(
+                canvas, index, pass, rect.right - rect.left, rect.bottom - rect.top);
+        canvas.restore();
+        return result;
+    }
+
+    public static abstract class SlotAnimation extends Animation {
+        protected float mProgress = 0;
+
+        public SlotAnimation() {
+            setInterpolator(new DecelerateInterpolator(4));
+            setDuration(1500);
+        }
+
+        @Override
+        protected void onCalculate(float progress) {
+            mProgress = progress;
+        }
+
+        abstract public void apply(GLCanvas canvas, int slotIndex, Rect target);
+    }
+
+    public static class RisingAnimation extends SlotAnimation {
+        private static final int RISING_DISTANCE = 128;
+
+        @Override
+        public void apply(GLCanvas canvas, int slotIndex, Rect target) {
+            canvas.translate(0, 0, RISING_DISTANCE * (1 - mProgress));
+        }
+    }
+
+    public static class ScatteringAnimation extends SlotAnimation {
+        private int PHOTO_DISTANCE = 1000;
+        private RelativePosition mCenter;
+
+        public ScatteringAnimation(RelativePosition center) {
+            mCenter = center;
+        }
+
+        @Override
+        public void apply(GLCanvas canvas, int slotIndex, Rect target) {
+            canvas.translate(
+                    (mCenter.getX() - target.centerX()) * (1 - mProgress),
+                    (mCenter.getY() - target.centerY()) * (1 - mProgress),
+                    slotIndex * PHOTO_DISTANCE * (1 - mProgress));
+            canvas.setAlpha(mProgress);
+        }
+    }
+
+    private class MyGestureListener implements GestureDetector.OnGestureListener {
+        private boolean isDown;
+
+        // We call the listener's onDown() when our onShowPress() is called and
+        // call the listener's onUp() when we receive any further event.
+        @Override
+        public void onShowPress(MotionEvent e) {
+            GLRoot root = getGLRoot();
+            root.lockRenderThread();
+            try {
+                if (isDown) return;
+                Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+                if (slot != null) {
+                    isDown = true;
+                    mListener.onDown(slot.index);
+                }
+            } finally {
+                root.unlockRenderThread();
+            }
+        }
+
+        private void cancelDown(boolean byLongPress) {
+            if (!isDown) return;
+            isDown = false;
+            mListener.onUp(byLongPress);
+        }
+
+        @Override
+        public boolean onDown(MotionEvent e) {
+            return false;
+        }
+
+        @Override
+        public boolean onFling(MotionEvent e1,
+                MotionEvent e2, float velocityX, float velocityY) {
+            cancelDown(false);
+            int scrollLimit = mLayout.getScrollLimit();
+            if (scrollLimit == 0) return false;
+            mScroller.fling((int) -velocityY, 0, scrollLimit);
+            invalidate();
+            return true;
+        }
+
+        @Override
+        public boolean onScroll(MotionEvent e1,
+                MotionEvent e2, float distanceX, float distanceY) {
+            cancelDown(false);
+            int overDistance = mScroller.startScroll(
+                    Math.round(distanceY), 0, mLayout.getScrollLimit());
+            invalidate();
+            return true;
+        }
+
+        @Override
+        public boolean onSingleTapUp(MotionEvent e) {
+            cancelDown(false);
+            if (mDownInScrolling) return true;
+            Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+            if (slot != null) {
+                mListener.onSingleTapUp(slot.index, slot.isTitle);
+            }
+            return true;
+        }
+
+        @Override
+        public void onLongPress(MotionEvent e) {
+            cancelDown(true);
+            if (mDownInScrolling) return;
+            lockRendering();
+            try {
+                Slot slot = mLayout.getSlotByPosition(e.getX(), e.getY());
+                if (slot != null) {
+                    mListener.onLongTap(slot.index, slot.isTitle);
+                }
+            } finally {
+                unlockRendering();
+            }
+        }
+    }
+
+    public void setStartIndex(int index) {
+        mStartIndex = index;
+    }
+
+    public void setSlotCount(int[] count) {
+        mLayout.setSlotCount(count);
+
+        // mStartIndex is applied the first time setSlotCount is called.
+        if (mStartIndex != INDEX_NONE) {
+            setCenterIndex(mStartIndex);
+            mStartIndex = INDEX_NONE;
+        }
+        // Reset the scroll position to avoid scrolling over the updated limit.
+        setScrollPosition(mScrollY);
+    }
+
+    public int getVisibleStart() {
+        return mLayout.getVisibleStart();
+    }
+
+    public int getVisibleEnd() {
+        return mLayout.getVisibleEnd();
+    }
+
+    public int getScrollX() {
+        return mScrollX;
+    }
+
+    public int getScrollY() {
+        return mScrollY;
+    }
+
+    public Rect getSlotRect(int slotIndex, GLView rootPane) {
+        // Get slot rectangle relative to this root pane.
+        Rect offset = new Rect();
+        rootPane.getBoundsOf(this, offset);
+        Rect r = getSlotRect(slotIndex);
+        if (r != null) {
+            r.offset(offset.left - getScrollX(),
+                    offset.top - getScrollY());
+            return r;
+        }
+        return offset;
+    }
+
+    public int getTitleWidth() {
+        return mWidth;
+    }
+
+    // This Spec class is used to specify the size of each slot in the SlotView.
+    // There are two ways to do it:
+    //
+    // Specify colsLand, colsPort, and slotGap: they specify the number
+    // of rows in landscape/portrait mode and the gap between slots. The
+    // width and height of each slot is determined automatically.
+    //
+    // The initial value of -1 means they are not specified.
+    public static class Spec {
+        public int colsLand = -1;
+        public int colsPort = -1;
+        public int titleHeight = -1;
+        public int slotGapPort = -1;
+        public int slotGapLand = -1;
+    }
+
+    public class Layout {
+        private int mVisibleStart;
+        private int mVisibleEnd;
+
+        public int mSlotSize;
+        private int mSlotWidth;
+        private int mSlotHeight;
+        private int mSlotGap;
+        private int[] mSlotCount;
+
+        private Spec mSpec;
+
+        private int mWidth;
+        private int mHeight;
+
+        private int mUnitCount;
+        private int mContentLength;
+        private int mScrollPosition;
+
+        public void setSlotSpec(TimeLineSlotView.Spec spec) {
+            mSpec = spec;
+        }
+
+        public void setSlotCount(int[] count) {
+            mSlotCount = count;
+            if (mHeight != 0) {
+                initLayoutParameters();
+                createSlots();
+            }
+        }
+
+        public int getSlotSize() {
+            return mSlotSize;
+        }
+
+        public Rect getSlotRect(int index) {
+            if (index >= mVisibleStart && index < mVisibleEnd && mVisibleEnd != 0) {
+                int height = 0, base = 0, top = 0;
+                for (int count : mSlotCount) {
+                    if (index == base) {
+                        return getSlotRect(getSlot(true, index, index, top));
+                    }
+                    top += mSpec.titleHeight;
+                    ++base;
+
+                    if (index >= base && index < base + count) {
+                        return getSlotRect(getSlot(false, index, base, top));
+                    }
+                    int rows = (count + mUnitCount - 1) / mUnitCount;
+                    top += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+                    base += count;
+                }
+            }
+            return null;
+        }
+
+        private void initLayoutParameters() {
+            mUnitCount = (mWidth > mHeight) ? mSpec.colsLand : mSpec.colsPort;
+            mSlotGap = (mWidth > mHeight) ? mSpec.slotGapLand: mSpec.slotGapPort;
+            mSlotWidth = Math.round((mWidth - (mUnitCount - 1) * mSlotGap) / mUnitCount);
+            mSlotHeight = mSlotWidth;
+            if (mRenderer != null) {
+                mRenderer.onSlotSizeChanged(mSlotWidth, mSlotHeight);
+            }
+        }
+
+        private void setSize(int width, int height) {
+            if (width != mWidth || height != mHeight) {
+                mWidth = width;
+                mHeight = height;
+                initLayoutParameters();
+                createSlots();
+            }
+        }
+
+        public void setScrollPosition(int position) {
+            if (mScrollPosition == position) return;
+            mScrollPosition = position;
+            updateVisibleSlotRange();
+        }
+
+        private Rect getSlotRect(Slot slot) {
+            int x, y, w, h;
+            if (slot.isTitle) {
+                x = 0;
+                y = slot.top;
+                w = mWidth;
+                h = mSpec.titleHeight;
+            } else {
+                x = slot.col * (mSlotWidth + mSlotGap);
+                y = slot.top;
+                w = mSlotWidth;
+                h = mSlotHeight;
+            }
+            return new Rect(x, y, x + w, y + h);
+        }
+
+        private synchronized void updateVisibleSlotRange() {
+            int position = mScrollPosition;
+            if (mSlotCount != null) {
+                Slot begin = getSlotByPosition(0, mScrollPosition, true, false),
+                        end = getSlotByPosition(0, mScrollPosition + mHeight, true, true);
+                if (begin == null && end != null && end.index == 0) {
+                    setVisibleRange(0, 0);
+                } else if (begin != null && end != null) {
+                    setVisibleRange(begin.index, end.index);
+                }
+            }
+        }
+
+        private void setVisibleRange(int start, int end) {
+            if (start == mVisibleStart && end == mVisibleEnd) return;
+            if (start < end) {
+                mVisibleStart = start;
+                mVisibleEnd = end;
+            } else {
+                mVisibleStart = mVisibleEnd = 0;
+            }
+            if (mRenderer != null) {
+                mRenderer.onVisibleRangeChanged(mVisibleStart, mVisibleEnd);
+            }
+        }
+
+        public int getVisibleStart() {
+            return mVisibleStart;
+        }
+
+        public int getVisibleEnd() {
+            return mVisibleEnd;
+        }
+
+        private Slot getSlot(boolean isTitle, int index, int indexBase, int top) {
+            if (isTitle) {
+                return new Slot(true, index, 0, top);
+            } else {
+                int row = (index - indexBase) / mUnitCount;
+                return new Slot(false, index, (index - indexBase) % mUnitCount,
+                        top + row * (mSlotHeight + mSlotGap));
+            }
+        }
+
+        public Slot getSlotByPosition(float x, float y, boolean rowStart, boolean roundUp) {
+            if (x < 0 || y < 0 || mSlotCount == null) {
+                return null;
+            }
+            int pos = (int) y, index = 0, top = 0;
+            for (int count : mSlotCount) {
+                int h = mSpec.titleHeight;
+                if (pos < top + h) {
+                    if (roundUp) {
+                        return getSlot(false, index + 1, index, top + h);
+                    } else {
+                        return getSlot(true, index, index, top);
+                    }
+                }
+                top += h;
+                ++index;
+
+                int rows = (count + mUnitCount - 1) / mUnitCount;
+                h = mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+                if (pos < top + h) {
+                    int row = ((int) pos - top) / (mSlotHeight + mSlotGap);
+                    int col = 0;
+                    if (roundUp) {
+                        int idx = (row + 1) * mUnitCount;
+                        if (idx > count)
+                            idx = count + 1;
+                        return getSlot(false, index + idx, index, top + mSlotHeight);
+                    }
+                    if (!rowStart) {
+                        col = ((int) x) / (mSlotWidth + mSlotGap);
+                        if (row * mUnitCount + col >= count) {
+                            break;
+                        }
+                    }
+                    return getSlot(false, index + row * mUnitCount + col, index, top);
+                }
+                top += h;
+                index += count;
+            }
+            if (roundUp) {
+                return getSlot(false, index, index, top);
+            }
+            return null;
+        }
+
+        public Slot getSlotByPosition(float x, float y) {
+            return getSlotByPosition(x, mScrollPosition + y, false, false);
+        }
+
+        public int getScrollLimit() {
+            return Math.max(0, mContentLength - mHeight);
+        }
+
+        public void createSlots() {
+            int height = 0;
+            int size = 0;
+            if (mSlotCount != null) {
+                for (int count : mSlotCount) {
+                    int rows = (count + mUnitCount - 1) / mUnitCount;
+                    height += mSlotHeight * rows + mSlotGap * (rows > 0 ? rows - 1 : 0);
+                    size += 1 + count;
+                }
+                height += mSpec.titleHeight * mSlotCount.length;
+                mContentLength = height;
+                mSlotSize = size;
+                updateVisibleSlotRange();
+            }
+        }
+    }
+
+    private static class Slot {
+        public boolean isTitle;
+        public int index;
+        public int col;
+        public int top;
+
+        public Slot(boolean isTitle, int index, int col, int top) {
+            this.isTitle = isTitle;
+            this.index = index;
+            this.col = col;
+            this.top = top;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/ui/TimeLineTitleMaker.java b/src/com/android/gallery3d/ui/TimeLineTitleMaker.java
new file mode 100755
index 0000000..52a3af2
--- /dev/null
+++ b/src/com/android/gallery3d/ui/TimeLineTitleMaker.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution
+ *
+ * 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.gallery3d.ui;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.view.View;
+
+import com.android.gallery3d.util.ThreadPool;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+import com.android.photos.data.GalleryBitmapPool;
+import org.codeaurora.gallery.R;
+
+import java.util.Locale;
+
+public class TimeLineTitleMaker {
+
+    private final String TAG = "TimelineTitleMaker";
+    private static final int BORDER_SIZE = 0;
+
+    private final TimeLineSlotRenderer.LabelSpec mSpec;
+    private final TextPaint mTitlePaint;
+    private final TextPaint mCountPaint;
+    private final Context mContext;
+    private final TimeLineSlotView mTimeLineSlotView;
+
+    private final int TIMELINETITLE_START_X;
+
+    public TimeLineTitleMaker(Context context, TimeLineSlotRenderer.LabelSpec spec, TimeLineSlotView slotView) {
+        mContext = context;
+        mSpec = spec;
+        mTimeLineSlotView = slotView;
+        mTitlePaint = getTextPaint(spec.timeLineTitleFontSize, spec.timeLineTitleTextColor , true);
+        mCountPaint = getTextPaint(spec.timeLineTitleFontSize, spec.timeLineNumberTextColor, true);
+        TIMELINETITLE_START_X = context.getResources().getDimensionPixelSize(
+                R.dimen.timeline_title_margin);
+    }
+
+    private static TextPaint getTextPaint(
+            int textSize, int color, boolean isBold) {
+        TextPaint paint = new TextPaint();
+        paint.setTextSize(textSize);
+        paint.setAntiAlias(true);
+        paint.setColor(color);
+        paint.setTypeface(Typeface.SANS_SERIF);
+        if (isBold) {
+            paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
+        }
+        return paint;
+    }
+
+    public ThreadPool.Job<Bitmap> requestTimeLineTitle( String title,
+            int photoCount, int videoCount) {
+        return new TimeLineTitle(title,photoCount, videoCount, mContext );
+    }
+
+    static void drawText(Canvas canvas,
+                         int x, int y, String text, int lengthLimit, TextPaint p) {
+        canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p);
+    }
+
+    private class TimeLineTitle implements ThreadPool.Job<Bitmap> {
+        private String mTitle;
+        private int mVideoCount;
+        private int mImageCount;
+        private Context mContext;
+        public TimeLineTitle(String title, int imageCount, int videoCount, Context context) {
+            mTitle = title;
+            mImageCount = imageCount;
+            mVideoCount = videoCount;
+            mContext = context;
+
+        }
+
+        @Override
+        public Bitmap run(JobContext jc) {
+            TimeLineSlotRenderer.LabelSpec spec = mSpec;
+
+            Bitmap bitmap;
+            int width = mTimeLineSlotView.getTitleWidth();
+            int height= spec.timeLineTitleHeight;
+            synchronized (this) {
+                bitmap = GalleryBitmapPool.getInstance().get(width, height);
+            }
+            if (bitmap == null) {
+                int borders = 2 * BORDER_SIZE;
+                bitmap = Bitmap.createBitmap(width + borders,
+                        height + borders, Config.ARGB_8888);
+            }
+            if (bitmap == null) {
+                return null;
+            }
+            Canvas canvas = new Canvas(bitmap);
+            canvas.clipRect(BORDER_SIZE, BORDER_SIZE,
+                    bitmap.getWidth() - BORDER_SIZE,
+                    bitmap.getHeight() - BORDER_SIZE);
+            canvas.drawColor(mSpec.timeLineTitleBackgroundColor, PorterDuff.Mode.SRC);
+
+            canvas.translate(BORDER_SIZE, BORDER_SIZE);
+
+
+            StringBuilder sb = new StringBuilder();
+            if(mImageCount != 0) {
+                sb.append(mContext.getResources().getQuantityString(R.plurals.number_of_photos, mImageCount, mImageCount));
+                if(mVideoCount!=0) {
+                    sb.append("  " +mContext.getResources().getQuantityString(
+                             R.plurals.number_of_videos, mVideoCount, mVideoCount));
+                }
+            } else {
+                if(mVideoCount != 0) {
+                    sb.append(mContext.getResources().getQuantityString(
+                            R.plurals.number_of_videos, mVideoCount, mVideoCount));
+                }
+            }
+            String countString = sb.toString();
+
+            if (jc.isCancelled()) return null;
+
+
+            int x;
+            int y = 0;
+            if (mTitle != null) {
+                mTitle = mTitle.toUpperCase();
+                x = TIMELINETITLE_START_X;
+                y = (height - spec.timeLineTitleFontSize)/2;
+                // re-calculate x for RTL
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    Rect titleBounds = new Rect();
+                    mTitlePaint.getTextBounds(
+                        mTitle, 0, mTitle.length(), titleBounds);
+                    int w = titleBounds.width();
+                    x = width - mTitle.length() - w;
+                }
+                drawText(canvas, x, y, mTitle, width-x, mTitlePaint);
+            }
+
+            if (countString != null) {
+
+                Rect mediaCountBounds = new Rect();
+                mCountPaint.getTextBounds(
+                        countString, 0, countString.length(), mediaCountBounds);
+                int w = mediaCountBounds.width();
+                y = (height - spec.timeLineTitleFontSize)/2;
+                x = width - TIMELINETITLE_START_X - w;
+                // re-calculate x for RTL
+                if (View.LAYOUT_DIRECTION_RTL == TextUtils
+                        .getLayoutDirectionFromLocale(Locale.getDefault())) {
+                    x = TIMELINETITLE_START_X;
+                }
+                drawText(canvas, x, y, countString,
+                        width - x, mCountPaint);
+            }
+            return bitmap;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/ui/UndoBarView.java b/src/com/android/gallery3d/ui/UndoBarView.java
index 42f12ae..6ac2428 100644
--- a/src/com/android/gallery3d/ui/UndoBarView.java
+++ b/src/com/android/gallery3d/ui/UndoBarView.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.view.MotionEvent;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.common.Utils;
 import com.android.gallery3d.glrenderer.GLCanvas;
 import com.android.gallery3d.glrenderer.NinePatchTexture;
diff --git a/src/com/android/gallery3d/util/CacheManager.java b/src/com/android/gallery3d/util/CacheManager.java
index ba466f7..0e8f3e7 100644
--- a/src/com/android/gallery3d/util/CacheManager.java
+++ b/src/com/android/gallery3d/util/CacheManager.java
@@ -46,13 +46,15 @@
             BlobCache cache = sCacheMap.get(filename);
             if (cache == null) {
                 File cacheDir = context.getExternalCacheDir();
-                String path = cacheDir.getAbsolutePath() + "/" + filename;
-                try {
-                    cache = new BlobCache(path, maxEntries, maxBytes, false,
-                            version);
-                    sCacheMap.put(filename, cache);
-                } catch (IOException e) {
-                    Log.e(TAG, "Cannot instantiate cache!", e);
+                if (cacheDir != null) {
+                    String path = cacheDir.getAbsolutePath() + "/" + filename;
+                    try {
+                        cache = new BlobCache(path, maxEntries, maxBytes, false,
+                                version);
+                        sCacheMap.put(filename, cache);
+                    } catch (IOException e) {
+                        Log.e(TAG, "Cannot instantiate cache!", e);
+                    }
                 }
             }
             return cache;
@@ -73,10 +75,12 @@
         pref.edit().putInt(KEY_CACHE_UP_TO_DATE, 1).commit();
 
         File cacheDir = context.getExternalCacheDir();
-        String prefix = cacheDir.getAbsolutePath() + "/";
+        if (cacheDir != null) {
+            String prefix = cacheDir.getAbsolutePath() + "/";
 
-        BlobCache.deleteFiles(prefix + "imgcache");
-        BlobCache.deleteFiles(prefix + "rev_geocoding");
-        BlobCache.deleteFiles(prefix + "bookmark");
+            BlobCache.deleteFiles(prefix + "imgcache");
+            BlobCache.deleteFiles(prefix + "rev_geocoding");
+            BlobCache.deleteFiles(prefix + "bookmark");
+        }
     }
 }
diff --git a/src/com/android/gallery3d/util/GDepth.java b/src/com/android/gallery3d/util/GDepth.java
new file mode 100644
index 0000000..39d8db1
--- /dev/null
+++ b/src/com/android/gallery3d/util/GDepth.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package com.android.gallery3d.util;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.net.Uri;
+import android.util.Base64;
+import android.util.Xml;
+
+import com.android.gallery3d.common.Utils;
+import com.android.gallery3d.exif.CountedDataInputStream;
+import com.android.gallery3d.exif.JpegHeader;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class GDepth {
+    private static final String TAG = "GDepth";
+    private static final String GDEPTH = "http://ns.google.com/photos/1.0/depthmap/";
+    private static final String GIMAGE = "http://ns.google.com/photos/1.0/image/";
+    private static final String XMPNOTE = "http://ns.adobe.com/xmp/note/";
+
+    private static final String SIGNATURE_STD = "http://ns.adobe.com/xap/1.0/\0";
+    private static final String SIGNATURE_EXT = "http://ns.adobe.com/xmp/extension/\0";
+
+    public static class Parser {
+        private byte[] image;
+        private byte[] ddm;
+        private int roiX = 0;
+        private int roiY = 0;
+        private int roiWidth = 0;
+        private int roiHeight = 0;
+
+        public boolean parse(Context context, Uri uri) {
+            InputStream is = null;
+            if (uri == null) return valid();
+            try {
+                is = context.getContentResolver().openInputStream(uri);
+                XMPStream stream = new XMPStream(is);
+                parse(stream);
+                if (stream.prepareExtended()) {
+                    parse(stream);
+                }
+            } catch (IOException ignored) {
+            } finally {
+                Utils.closeSilently(is);
+            }
+            return valid();
+        }
+
+        public boolean valid() {
+            return ddm != null && image != null;
+        }
+
+        private void parse(XMPStream stream) throws IOException {
+            XmlPullParser parser = Xml.newPullParser();
+            try {
+                parser.setInput(stream, null);
+                parser.nextTag();
+                int event = parser.next();
+                while (event != XmlPullParser.END_DOCUMENT) {
+                    if (event == XmlPullParser.START_TAG && "Description".equals(parser.getName())) {
+                        int count = parser.getAttributeCount();
+                        for (int i = 0; i < count; ++i) {
+                            String ns = parser.getAttributeNamespace(i);
+                            if (GDEPTH.equals(ns)) {
+                                String name = parser.getAttributeName(i);
+                                String value = parser.getAttributeValue(i);
+                                if ("Data".equals(name)) {
+                                    ddm = parseData(value);
+                                } else if ("RoiX".equals(name)) {
+                                    roiX = Integer.parseInt(value);
+                                } else if ("RoiY".equals(name)) {
+                                    roiY = Integer.parseInt(value);
+                                } else if ("RoiWidth".equals(name)) {
+                                    roiWidth = Integer.parseInt(value);
+                                } else if ("RoiHeight".equals(name)) {
+                                    roiHeight = Integer.parseInt(value);
+                                }
+                            } else if (GIMAGE.equals(ns)) {
+                                if ("Data".equals(parser.getAttributeName(i))) {
+                                    image = parseData(parser.getAttributeValue(i));
+                                }
+                            } else if (XMPNOTE.equals(ns)) {
+                                if ("HasExtendedXMP".equals(parser.getAttributeName(i))) {
+                                    stream.setExtended(parser.getAttributeValue(i));
+                                }
+                            }
+                        }
+                    }
+                    event = parser.next();
+                }
+            } catch (XmlPullParserException ignored) {
+            }
+        }
+
+        private byte[] parseData(String base64data) {
+            return Base64.decode(base64data, Base64.DEFAULT);
+        }
+
+        // decode base64 encoded (and compressed) data into Bitmaps
+        public Image decode() {
+            Image img = new Image();
+            img.bitmap = BitmapFactory.decodeByteArray(image, 0, image.length);
+            Log.d(TAG, "bitmap: " + img.bitmap.getWidth() + "x" + img.bitmap.getHeight());
+            image = null;
+
+            img.depthMap = decodeDepthMap();
+            Log.d(TAG, "ddm: " + img.depthMap.getWidth() + "x" + img.depthMap.getHeight());
+            ddm = null;
+
+            if (roiWidth == 0 || roiHeight == 0) {
+                roiWidth = img.bitmap.getWidth();
+                roiHeight = img.bitmap.getHeight();
+            }
+            img.roi = new int[]{roiX, roiY, roiWidth, roiHeight};
+            return img;
+        }
+
+        private Bitmap decodeDepthMap() {
+            Bitmap bitmap = BitmapFactory.decodeByteArray(ddm, 0, ddm.length);
+            int width = bitmap.getWidth(), height = bitmap.getHeight();
+            int[] pixels = new int[width * height];
+            bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
+            Bitmap out = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
+            for (int i = 0; i < pixels.length; ++i) {
+                int p = pixels[i];
+                pixels[i] = (p & 0xff) << 24;
+            }
+            out.setPixels(pixels, 0, width, 0, 0, width, height);
+            return out;
+        }
+    }
+
+    public static class Image {
+        public Bitmap bitmap;
+        public Bitmap depthMap;
+        public int[] roi;
+
+        public boolean valid() {
+            return bitmap != null && depthMap != null && roi != null;
+        }
+    }
+
+    private static class XMPStream extends InputStream {
+        private static final int START = 0;
+        private static final int STANDARD = 1;
+        private static final int EXTEND = 2;
+        private static final int END = 3;
+
+        private CountedDataInputStream stream;
+        private String extended;
+        private int status = START;
+        private int chunk = 0;
+
+        XMPStream(InputStream is) {
+            stream = new CountedDataInputStream(is);
+        }
+
+        private boolean next() throws IOException {
+            while (true) {
+                short marker = stream.readShort();
+                if (marker == JpegHeader.EOI || JpegHeader.isSofMarker(marker)) {
+                    status = END;
+                    return false;
+                }
+                if (marker == JpegHeader.APP1) {
+                    int length = stream.readUnsignedShort();
+                    if (status == STANDARD) {
+                        if (length < SIGNATURE_STD.length()) {
+                            stream.skipOrThrow(length - 2);
+                        } else {
+                            String s = stream.readString(SIGNATURE_STD.length());
+                            if (SIGNATURE_STD.equals(s)) {
+                                chunk = length - SIGNATURE_STD.length() - 2;
+                                return true;
+                            } else {
+                                stream.skipOrThrow(length - 2 - SIGNATURE_STD.length());
+                            }
+                        }
+                    } else {
+                        if (length < SIGNATURE_EXT.length()) {
+                            stream.skipOrThrow(length - 2);
+                        } else {
+                            String s = stream.readString(SIGNATURE_EXT.length());
+                            if (SIGNATURE_EXT.equals(s)) {
+                                if (extended == null) return false;
+                                String guid = stream.readString(32);
+                                if (!extended.equals(guid)) continue;
+                                // skip 2 32-bit integers
+                                stream.skipOrThrow(8);
+                                chunk = length - SIGNATURE_EXT.length() - 42;
+                                return true;
+                            } else {
+                                stream.skipOrThrow(length - 2 - SIGNATURE_EXT.length());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        void setExtended(String guid) {
+            extended = guid;
+        }
+
+        boolean prepareExtended() {
+            if (extended != null) {
+                status = EXTEND;
+            }
+            return extended != null;
+        }
+
+        @Override
+        public int read() throws IOException {
+            byte[] b = new byte[1];
+            int r = read(b, 0, 1);
+            return r == -1 ? r : b[0];
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (chunk > 0) {
+                int l = chunk > len ? len : chunk;
+                chunk -= l;
+                return stream.read(b, off, l);
+            }
+            if (status == START) {
+                if (stream.readShort() != JpegHeader.SOI) return -1;
+                status = STANDARD;
+            } else if (status == STANDARD || status == END) {
+                return -1;
+            }
+            if (next() && chunk > 0) {
+                int l = chunk > len ? len : chunk;
+                chunk -= l;
+                return stream.read(b, off, l);
+            }
+            return -1;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/util/GIFView.java b/src/com/android/gallery3d/util/GIFView.java
new file mode 100755
index 0000000..7bcc52d
--- /dev/null
+++ b/src/com/android/gallery3d/util/GIFView.java
@@ -0,0 +1,207 @@
+package com.android.gallery3d.util;
+
+import org.codeaurora.gallery.R;
+
+import android.content.Context;
+import android.content.ContentResolver;
+import android.content.res.AssetManager;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
+
+public class GIFView extends ImageView implements GifAction {
+
+    private static final String  TAG            = "GIFView";
+    private static final float   SCALE_LIMIT    = 4;
+    private static final long    FRAME_DELAY    = 200; //milliseconds
+
+    private GifDecoder           mGifDecoder    = null;
+    private Bitmap               mCurrentImage  = null;
+    private DrawThread           mDrawThread    = null;
+
+    private Uri                  mUri;
+    private Context              mContext;
+
+    public GIFView(Context context) {
+        super(context);
+        mContext = context;
+    }
+
+    public boolean setDrawable(Uri uri) {
+        if (null == uri) {
+            return false;
+        }
+        mUri = uri;
+
+        InputStream is = getInputStream(uri);
+        if (is == null || (getFileSize (is) == 0)) {
+            return false;
+        }
+        startDecode(is);
+        return true;
+    }
+
+    private int getFileSize (InputStream is) {
+        if(is == null) return 0;
+
+        int size = 0;
+        try {
+            if (is instanceof FileInputStream) {
+                FileInputStream f = (FileInputStream) is;
+                size = (int) f.getChannel().size();
+            } else {
+                while (-1 != is.read()) {
+                    size++;
+                }
+            }
+
+        } catch (IOException e) {
+            Log.e(TAG, "catch exception:" + e);
+        }
+
+        return size;
+
+    }
+
+    private InputStream getInputStream (Uri uri) {
+        ContentResolver cr = mContext.getContentResolver();
+        InputStream input = null;
+        try {
+            input = cr.openInputStream(uri);
+        } catch (IOException e) {
+            Log.e(TAG, "catch exception:" + e);
+        }
+        return input;
+    }
+
+    private void startDecode(InputStream is) {
+        freeGifDecoder();
+        mGifDecoder = new GifDecoder(is, this);
+        mGifDecoder.start();
+    }
+
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        if (mGifDecoder == null) {
+            return;
+        }
+
+        if (mCurrentImage == null) {
+            mCurrentImage = mGifDecoder.getImage();
+        }
+        if (mCurrentImage == null) {
+            // if this gif can not be displayed, just try to show it as jpg by parsing mUri
+            setImageURI(mUri);
+            return;
+        }
+        setImageURI(null);
+        int saveCount = canvas.getSaveCount();
+        canvas.save();
+        canvas.translate(getPaddingLeft(), getPaddingTop());
+        Rect sRect = null;
+        Rect dRect = null;
+
+        int imageHeight = mCurrentImage.getHeight();
+        int imageWidth = mCurrentImage.getWidth();
+
+        int displayHeight = ViewGifImage.mDM.heightPixels;
+        int displayWidth = ViewGifImage.mDM.widthPixels;
+
+        int width, height;
+        if (imageWidth >= displayWidth || imageHeight >= displayHeight) {
+            // scale-down the image
+            if (imageWidth * displayHeight > displayWidth * imageHeight) {
+                width = displayWidth;
+                height = (imageHeight * width) / imageWidth;
+            } else {
+                height = displayHeight;
+                width = (imageWidth * height) / imageHeight;
+            }
+        } else {
+            // scale-up the image
+            float scale = Math.min(SCALE_LIMIT, Math.min(displayWidth / (float) imageWidth,
+                    displayHeight / (float) imageHeight));
+            width = (int) (imageWidth * scale);
+            height = (int) (imageHeight * scale);
+        }
+        dRect = new Rect((displayWidth - width) / 2, (displayHeight - height) / 2,
+                (displayWidth + width) / 2, (displayHeight + height) / 2);
+        canvas.drawBitmap(mCurrentImage, sRect, dRect, null);
+        canvas.restoreToCount(saveCount);
+    }
+
+    public void parseOk(boolean parseStatus, int frameIndex) {
+        if (parseStatus) {
+            //indicates the start of a new GIF
+            if (mGifDecoder != null && frameIndex == -1
+                    && mGifDecoder.getFrameCount() > 1) {
+                if (mDrawThread != null) {
+                    mDrawThread = null;
+                }
+                mDrawThread = new DrawThread();
+                mDrawThread.start();
+            }
+        } else {
+            Log.e(TAG, "parse error");
+        }
+    }
+
+    private Handler mRedrawHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            invalidate();
+        }
+    };
+
+    private class DrawThread extends Thread {
+        public void run() {
+            while (true) {
+                if (mGifDecoder == null || !isShown() || mRedrawHandler == null) {
+                    break;
+                }
+                GifFrame frame = mGifDecoder.next();
+                mCurrentImage = frame.mImage;
+
+                Message msg = mRedrawHandler.obtainMessage();
+                mRedrawHandler.sendMessage(msg);
+                try {
+                    Thread.sleep(getDelay(frame));
+                } catch (InterruptedException e) {
+                    Log.e(TAG, "catch exception:" + e);
+                }
+            }
+        }
+
+    }
+
+    private long getDelay (GifFrame frame) {
+        //in milliseconds
+        return frame.mDelayInMs == 0 ? FRAME_DELAY : frame.mDelayInMs;
+    }
+
+    private void freeGifDecoder () {
+        if (mGifDecoder != null) {
+            mGifDecoder.free();
+            mGifDecoder = null;
+        }
+
+    }
+
+    public void freeMemory() {
+        if (mDrawThread != null) {
+            mDrawThread = null;
+        }
+        freeGifDecoder();
+    }
+}
diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java
index 8fb926c..3507b08 100644
--- a/src/com/android/gallery3d/util/GalleryUtils.java
+++ b/src/com/android/gallery3d/util/GalleryUtils.java
@@ -17,11 +17,13 @@
 package com.android.gallery3d.util;
 
 import android.annotation.TargetApi;
+import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -32,18 +34,18 @@
 import android.os.StatFs;
 import android.preference.PreferenceManager;
 import android.provider.MediaStore;
+import android.telephony.TelephonyManager;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.WindowManager;
+import android.widget.Toast;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryActivity;
-import com.android.gallery3d.app.PackagesMonitor;
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.DataManager;
 import com.android.gallery3d.data.MediaItem;
 import com.android.gallery3d.ui.TiledScreenNail;
-import com.android.gallery3d.util.IntentHelper;
 import com.android.gallery3d.util.ThreadPool.CancelListener;
 import com.android.gallery3d.util.ThreadPool.JobContext;
 
@@ -72,6 +74,8 @@
     private static final String KEY_CAMERA_UPDATE = "camera-update";
     private static final String KEY_HAS_CAMERA = "has-camera";
 
+    private static final String KEY_PACKAGES_VERSION  = "packages-version";
+
     private static float sPixelDensity = -1f;
     private static boolean sCameraAvailableInitialized = false;
     private static boolean sCameraAvailable;
@@ -201,7 +205,7 @@
     }
 
     public static boolean isEditorAvailable(Context context, String mimeType) {
-        int version = PackagesMonitor.getPackagesVersion(context);
+        int version = getPackagesVersion(context);
 
         String updateKey = PREFIX_PHOTO_EDITOR_UPDATE + mimeType;
         String hasKey = PREFIX_HAS_PHOTO_EDITOR + mimeType;
@@ -220,7 +224,7 @@
     }
 
     public static boolean isAnyCameraAvailable(Context context) {
-        int version = PackagesMonitor.getPackagesVersion(context);
+        int version = getPackagesVersion(context);
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
         if (prefs.getInt(KEY_CAMERA_UPDATE, 0) != version) {
             PackageManager packageManager = context.getPackageManager();
@@ -236,7 +240,7 @@
     public static boolean isCameraAvailable(Context context) {
         if (sCameraAvailableInitialized) return sCameraAvailable;
         PackageManager pm = context.getPackageManager();
-        Intent cameraIntent = IntentHelper.getCameraIntent(context);
+        Intent cameraIntent = IntentHelper.getCameraIntent();
         List<ResolveInfo> apps = pm.queryIntentActivities(cameraIntent, 0);
         sCameraAvailableInitialized = true;
         sCameraAvailable = !apps.isEmpty();
@@ -275,7 +279,7 @@
         return String.format(Locale.ENGLISH, format, latitude, longitude);
     }
 
-    public static void showOnMap(Context context, double latitude, double longitude) {
+    public static void showOnMap(final Context context, double latitude, double longitude) {
         try {
             // We don't use "geo:latitude,longitude" because it only centers
             // the MapView to the specified location, but we need a marker
@@ -292,8 +296,21 @@
             // Use the "geo intent" if no GMM is installed
             Log.e(TAG, "GMM activity not found!", e);
             String url = formatLatitudeLongitude("geo:%f,%f", latitude, longitude);
-            Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
-            context.startActivity(mapsIntent);
+            try {
+                Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+                context.startActivity(mapsIntent);
+            } catch (ActivityNotFoundException ex) {
+                Log.e(TAG, "Map view activity not found! url = " + url, ex);
+                ((Activity)context).runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        Toast.makeText(context,
+                                context.getString(R.string.map_activity_not_found_err),
+                                Toast.LENGTH_SHORT).show();
+                    }
+                });
+
+            }
         }
     }
 
@@ -354,10 +371,10 @@
         int typeBits = 0;
         String type = intent.resolveType(context);
 
-        if (MIME_TYPE_ALL.equals(type)) {
+        if (MIME_TYPE_ALL.equals(type) ||
+                MIME_TYPE_IMAGE.equals(type)) {
             typeBits = DataManager.INCLUDE_ALL;
-        } else if (MIME_TYPE_IMAGE.equals(type) ||
-                DIR_TYPE_IMAGE.equals(type)) {
+        } else if (DIR_TYPE_IMAGE.equals(type)) {
             typeBits = DataManager.INCLUDE_IMAGE;
         } else if (MIME_TYPE_VIDEO.equals(type) ||
                 DIR_TYPE_VIDEO.equals(type)) {
@@ -406,4 +423,57 @@
         int h = item.getHeight();
         return (h > 0 && w / h >= 2);
     }
+ // Newly added methods
+    public static int getIntPref(Context context, String name, int def) {
+        SharedPreferences prefs =
+            context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        return prefs.getInt(name, def);
+    }
+
+    public static void setIntPref(Context context, String name, int value) {
+        SharedPreferences prefs =
+            context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        Editor ed = prefs.edit();
+        ed.putInt(name, value);
+        ed.commit();
+    }
+
+    public static boolean getBooleanPref(Context context, String name, boolean def) {
+        SharedPreferences prefs =
+                context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        return prefs.getBoolean(name, def);
+    }
+
+    public static void setBooleanPref(Context context, String name, boolean value) {
+        SharedPreferences prefs =
+                context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        Editor ed = prefs.edit();
+        ed.putBoolean(name, value);
+        ed.commit();
+    }
+
+    public static String getStringPref(Context context, String name, String def) {
+        SharedPreferences prefs =
+                context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        return prefs.getString(name, def);
+    }
+
+    public static void setStringPref(Context context, String name, String value) {
+        SharedPreferences prefs =
+                context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
+        Editor ed = prefs.edit();
+        ed.putString(name, value);
+        ed.commit();
+    }
+
+    public static boolean isTelephonyCallInProgress(Context context) {
+        TelephonyManager telephonyManager =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        return telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
+    }
+
+    public static int getPackagesVersion(Context context) {
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        return prefs.getInt(KEY_PACKAGES_VERSION, 1);
+    }
 }
diff --git a/src/com/android/gallery3d/util/GifAction.java b/src/com/android/gallery3d/util/GifAction.java
new file mode 100644
index 0000000..88e3cde
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifAction.java
@@ -0,0 +1,5 @@
+package com.android.gallery3d.util;
+
+public interface GifAction {
+    public void parseOk(boolean parseStatus, int frameIndex);
+}
diff --git a/src/com/android/gallery3d/util/GifDecoder.java b/src/com/android/gallery3d/util/GifDecoder.java
new file mode 100755
index 0000000..5b07623
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifDecoder.java
@@ -0,0 +1,731 @@
+package com.android.gallery3d.util;
+
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.util.Log;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+public class GifDecoder extends Thread {
+
+    public static final int STATUS_PARSING = 0;
+    public static final int STATUS_FORMAT_ERROR = 1;
+    public static final int STATUS_OPEN_ERROR = 2;
+    public static final int STATUS_FINISH = -1;
+
+    private InputStream mIS;
+    private int mStatus;
+
+    public int mWidth; // full image width
+    public int mHeight; // full image height
+    private boolean mGctFlag; // global color table used
+    private int mGctSize; // size of global color table
+    private int mLoopCount = 1; // iterations; 0 = repeat forever
+
+    private int[] mGct; // global color table
+    private int[] mLct; // local color table
+    private int[] mAct; // active color table
+
+    private int mBgIndex; // background color index
+    private int mBgColor; // background color
+    private int mLastBgColor; // previous bg color
+    private int mPixelAspect; // pixel aspect ratio
+
+    private boolean mLctFlag; // local color table flag
+    private boolean mInterlace; // interlace flag
+    private int mLctSize; // local color table size
+
+    private int mIx, mIy, mIw, mIh; // current image rectangle
+    private int mLrx, mLry, mLrw, mLrh;
+    private Bitmap mImage; // current frame
+    private Bitmap mLastImage; // previous frame
+    private GifFrame mCurrentFrame = null;
+
+    private boolean mIsShow = false;
+
+    private byte[] mBlock = new byte[256]; // current data block
+    private int mBlockSize = 0; // block size
+    private int mDispose = 0;
+    private int mLastDispose = 0;
+    private boolean mTransparency = false; // use transparent color
+    private int mDelay = 0; // delay in milliseconds
+    private int mTransIndex; // transparent color index
+
+    // max decoder pixel stack size
+    private static final int MaxStackSize = 4096;
+
+    // LZW decoder working arrays
+    private short[] mPrefix;
+    private byte[] mSuffix;
+    private byte[] mPixelStack;
+    private byte[] mPixels;
+
+    private GifFrame mGifFrame; // frames read from current file
+    private int mFrameCount;
+
+    private GifAction mGifAction = null;
+
+    private byte[] mGifData = null;
+
+    public GifDecoder(byte[] data, GifAction act) {
+        mGifData = data;
+        mGifAction = act;
+    }
+
+    public GifDecoder(InputStream is, GifAction act) {
+        mIS = is;
+        mGifAction = act;
+    }
+
+    public void run() {
+        if (mIS != null) {
+            readStream();
+        } else if (mGifData != null) {
+            readByte();
+        }
+    }
+
+    public void free() {
+        freeFrame();
+        freeIS();
+        freeImage();
+    }
+
+    public int getStatus() {
+        return mStatus;
+    }
+
+    public boolean parseOk() {
+        return mStatus == STATUS_FINISH;
+    }
+
+    public int getDelay(int n) {
+        mDelay = -1;
+        if ((n >= 0) && (n < mFrameCount)) {
+            GifFrame f = getFrame(n);
+            if (f != null) {
+                mDelay = f.mDelayInMs;
+            }
+        }
+        return mDelay;
+    }
+
+    public int[] getDelays() {
+        GifFrame f = mGifFrame;
+        int[] d = new int[mFrameCount];
+        int i = 0;
+        while (f != null && i < mFrameCount) {
+            d[i] = f.mDelayInMs;
+            f = f.mNextFrame;
+            i++;
+        }
+        return d;
+    }
+
+    public int getFrameCount() {
+        return mFrameCount;
+    }
+
+    public Bitmap getImage() {
+        return getFrameImage(0);
+    }
+
+    public int getLoopCount() {
+        return mLoopCount;
+    }
+
+    private void setPixels() {
+        int[] dest = new int[mWidth * mHeight];
+        // fill in starting image contents based on last image's dispose code
+        if (mLastDispose > 0) {
+            if (mLastDispose == 3) {
+                // use image before last
+                int n = mFrameCount - 2;
+                if (n > 0) {
+                    mLastImage = getPreUndisposedImage(n - 1);
+                } else {
+                    mLastImage = null;
+                }
+            }
+            if (mLastImage != null) {
+                mLastImage.getPixels(dest, 0, mWidth, 0, 0, mWidth, mHeight);
+                // copy pixels
+                if (mLastDispose == 2) {
+                    // fill last image rect area with background color
+                    int c = 0;
+                    if (!mTransparency) {
+                        c = mLastBgColor;
+                    }
+                    for (int i = 0; i < mLrh; i++) {
+                        int n1 = (mLry + i) * mWidth + mLrx;
+                        int n2 = n1 + mLrw;
+                        for (int k = n1; k < n2; k++) {
+                            dest[k] = c;
+                        }
+                    }
+                }
+            }
+        }
+
+        // copy each source line to the appropriate place in the destination
+        int pass = 1;
+        int inc = 8;
+        int iline = 0;
+        for (int i = 0; i < mIh; i++) {
+            int line = i;
+            if (mInterlace) {
+                if (iline >= mIh) {
+                    pass++;
+                    switch (pass) {
+                        case 2:
+                            iline = 4;
+                            break;
+                        case 3:
+                            iline = 2;
+                            inc = 4;
+                            break;
+                        case 4:
+                            iline = 1;
+                            inc = 2;
+                    }
+                }
+                line = iline;
+                iline += inc;
+            }
+            line += mIy;
+            if (line < mHeight) {
+                int k = line * mWidth;
+                int dx = k + mIx; // start of line in dest
+                int dlim = dx + mIw; // end of dest line
+                if ((k + mWidth) < dlim) {
+                    dlim = k + mWidth; // past dest edge
+                }
+                int sx = i * mIw; // start of line in source
+                while (dx < dlim) {
+                    // map color and insert in destination
+                    int index = ((int) mPixels[sx++]) & 0xff;
+                    int c = mAct[index];
+                    if (c != 0) {
+                        dest[dx] = c;
+                    }
+                    dx++;
+                }
+            }
+        }
+        mImage = Bitmap.createBitmap(dest, mWidth, mHeight, Config.ARGB_4444);
+    }
+
+    public Bitmap getFrameImage(int n) {
+        GifFrame frame = getFrame(n);
+        if (frame == null) {
+            return null;
+        } else {
+            return frame.mImage;
+        }
+    }
+
+    public GifFrame getCurrentFrame() {
+        return mCurrentFrame;
+    }
+
+    public GifFrame getFrame(int n) {
+        GifFrame frame = mGifFrame;
+        int i = 0;
+        while (frame != null) {
+            if (i == n) {
+                return frame;
+            } else {
+                frame = frame.mNextFrame;
+            }
+            i++;
+        }
+        return null;
+    }
+
+    private Bitmap getPreUndisposedImage(int n) {
+        Bitmap preUndisposedImage = null;
+        GifFrame frame = mGifFrame;
+        int i = 0;
+        while (frame != null && i <= n) {
+            if (frame.mDispose == 1) {
+                preUndisposedImage = frame.mImage;
+            } else {
+                frame = frame.mNextFrame;
+            }
+            i++;
+        }
+        return preUndisposedImage;
+    }
+
+    public void reset() {
+        mCurrentFrame = mGifFrame;
+    }
+
+    public GifFrame next() {
+        if (mIsShow == false) {
+            mIsShow = true;
+            return mGifFrame;
+        } else {
+            if (mStatus == STATUS_PARSING) {
+                if (mCurrentFrame.mNextFrame != null) {
+                    mCurrentFrame = mCurrentFrame.mNextFrame;
+                }
+            } else {
+                mCurrentFrame = mCurrentFrame.mNextFrame;
+                if (mCurrentFrame == null) {
+                    mCurrentFrame = mGifFrame;
+                }
+            }
+            return mCurrentFrame;
+        }
+    }
+
+    private int readByte() {
+        mIS = new ByteArrayInputStream(mGifData);
+        mGifData = null;
+        return readStream();
+    }
+
+    private int readStream() {
+        init();
+        if (mIS != null) {
+            readHeader();
+            if (!err()) {
+                readContents();
+                if (mFrameCount < 0) {
+                    mStatus = STATUS_FORMAT_ERROR;
+                    if (mGifAction != null) {
+                        mGifAction.parseOk(false, -1);
+                    }
+                } else {
+                    mStatus = STATUS_FINISH;
+                    if (mGifAction != null) {
+                        mGifAction.parseOk(true, -1);
+                    }
+                }
+            }
+            try {
+                mIS.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        } else {
+            mStatus = STATUS_OPEN_ERROR;
+            if (mGifAction != null) {
+                mGifAction.parseOk(false, -1);
+            }
+        }
+        return mStatus;
+    }
+
+    private void decodeImageData() {
+        int NullCode = -1;
+        int npix = mIw * mIh;
+        int available, clear, code_mask, code_size, end_of_information, in_code, old_code,
+                bits, code, count, i, datum, data_size, first, top, bi, pi;
+
+        if ((mPixels == null) || (mPixels.length < npix)) {
+            mPixels = new byte[npix]; // allocate new pixel array
+        }
+        if (mPrefix == null) {
+            mPrefix = new short[MaxStackSize];
+        }
+        if (mSuffix == null) {
+            mSuffix = new byte[MaxStackSize];
+        }
+        if (mPixelStack == null) {
+            mPixelStack = new byte[MaxStackSize + 1];
+        }
+        // Initialize GIF data stream decoder.
+        data_size = read();
+        clear = 1 << data_size;
+        end_of_information = clear + 1;
+        available = clear + 2;
+        old_code = NullCode;
+        code_size = data_size + 1;
+        code_mask = (1 << code_size) - 1;
+        for (code = 0; code < clear; code++) {
+            mPrefix[code] = 0;
+            mSuffix[code] = (byte) code;
+        }
+
+        // Decode GIF pixel stream.
+        datum = bits = count = first = top = pi = bi = 0;
+        for (i = 0; i < npix;) {
+            if (top == 0) {
+                if (bits < code_size) {
+                    // Load bytes until there are enough bits for a code.
+                    if (count == 0) {
+                        // Read a new data block.
+                        count = readBlock();
+                        if (count <= 0) {
+                            break;
+                        }
+                        bi = 0;
+                    }
+                    datum += (((int) mBlock[bi]) & 0xff) << bits;
+                    bits += 8;
+                    bi++;
+                    count--;
+                    continue;
+                }
+                // Get the next code.
+                code = datum & code_mask;
+                datum >>= code_size;
+                bits -= code_size;
+
+                // Interpret the code
+                if ((code > available) || (code == end_of_information)) {
+                    break;
+                }
+                if (code == clear) {
+                    // Reset decoder.
+                    code_size = data_size + 1;
+                    code_mask = (1 << code_size) - 1;
+                    available = clear + 2;
+                    old_code = NullCode;
+                    continue;
+                }
+                if (old_code == NullCode) {
+                    mPixelStack[top++] = mSuffix[code];
+                    old_code = code;
+                    first = code;
+                    continue;
+                }
+                in_code = code;
+                if (code == available) {
+                    mPixelStack[top++] = (byte) first;
+                    code = old_code;
+                }
+                while (code > clear) {
+                    mPixelStack[top++] = mSuffix[code];
+                    code = mPrefix[code];
+                }
+                first = ((int) mSuffix[code]) & 0xff;
+                // Add a new string to the string table,
+                if (available >= MaxStackSize) {
+                    break;
+                }
+                mPixelStack[top++] = (byte) first;
+                mPrefix[available] = (short) old_code;
+                mSuffix[available] = (byte) first;
+                available++;
+                if (((available & code_mask) == 0)
+                        && (available < MaxStackSize)) {
+                    code_size++;
+                    code_mask += available;
+                }
+                old_code = in_code;
+            }
+
+            // Pop a pixel off the pixel stack.
+            top--;
+            mPixels[pi++] = mPixelStack[top];
+            i++;
+        }
+        for (i = pi; i < npix; i++) {
+            mPixels[i] = 0; // clear missing pixels
+        }
+    }
+
+    private boolean err() {
+        return mStatus != STATUS_PARSING;
+    }
+
+    private void init() {
+        mStatus = STATUS_PARSING;
+        mFrameCount = 0;
+        mGifFrame = null;
+        mGct = null;
+        mLct = null;
+    }
+
+    private int read() {
+        int curByte = 0;
+        try {
+            curByte = mIS.read();
+        } catch (Exception e) {
+            mStatus = STATUS_FORMAT_ERROR;
+        }
+        return curByte;
+    }
+
+    private int readBlock() {
+        mBlockSize = read();
+        int n = 0;
+        if (mBlockSize > 0) {
+            try {
+                int count = 0;
+                while (n < mBlockSize) {
+                    count = mIS.read(mBlock, n, mBlockSize - n);
+                    if (count == -1) {
+                        break;
+                    }
+                    n += count;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if (n < mBlockSize) {
+                mStatus = STATUS_FORMAT_ERROR;
+            }
+        }
+        return n;
+    }
+
+    private int[] readColorTable(int ncolors) {
+        int nbytes = 3 * ncolors;
+        int[] tab = null;
+        byte[] c = new byte[nbytes];
+        int n = 0;
+        try {
+            n = mIS.read(c);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        if (n < nbytes) {
+            mStatus = STATUS_FORMAT_ERROR;
+        } else {
+            tab = new int[256]; // max size to avoid bounds checks
+            int i = 0;
+            int j = 0;
+            while (i < ncolors) {
+                int r = ((int) c[j++]) & 0xff;
+                int g = ((int) c[j++]) & 0xff;
+                int b = ((int) c[j++]) & 0xff;
+                tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
+            }
+        }
+        return tab;
+    }
+
+    private void readContents() {
+        // read GIF file content blocks
+        boolean done = false;
+        while (!(done || err())) {
+            int code = read();
+            switch (code) {
+                case 0x2C: // image separator
+                    readImage();
+                    break;
+                case 0x21: // extension
+                    code = read();
+                    switch (code) {
+                        case 0xf9: // graphics control extension
+                            readGraphicControlExt();
+                            break;
+                        case 0xff: // application extension
+                            readBlock();
+                            String app = "";
+                            for (int i = 0; i < 11; i++) {
+                                app += (char) mBlock[i];
+                            }
+                            if (app.equals("NETSCAPE2.0")) {
+                                readNetscapeExt();
+                            } else {
+                                skip(); // don't care
+                            }
+                            break;
+                        default: // uninteresting extension
+                            skip();
+                    }
+                    break;
+                case 0x3b: // terminator
+                    done = true;
+                    break;
+                case 0x00: // bad byte, but keep going and see what happens
+                    break;
+                default:
+                    mStatus = STATUS_FORMAT_ERROR;
+            }
+        }
+    }
+
+    private void readGraphicControlExt() {
+        read(); // block size
+        int packed = read(); // packed fields
+        mDispose = (packed & 0x1c) >> 2; // disposal method
+        if (mDispose == 0) {
+            mDispose = 1; // elect to keep old image if discretionary
+        }
+        mTransparency = (packed & 1) != 0;
+        mDelay = readShort() * 10; // delay in milliseconds
+        mTransIndex = read(); // transparent color index
+        read(); // block terminator
+    }
+
+    private void readHeader() {
+        String id = "";
+        for (int i = 0; i < 6; i++) {
+            id += (char) read();
+        }
+        if (!id.startsWith("GIF")) {
+            mStatus = STATUS_FORMAT_ERROR;
+            return;
+        }
+        readLSD();
+        if (mGctFlag && !err()) {
+            mGct = readColorTable(mGctSize);
+            mBgColor = mGct[mBgIndex];
+        }
+    }
+
+    private void readImage() {
+        mIx = readShort(); // (sub)image position & size
+        mIy = readShort();
+        mIw = readShort();
+        mIh = readShort();
+        int packed = read();
+        mLctFlag = (packed & 0x80) != 0; // 1 - local color table flag
+        mInterlace = (packed & 0x40) != 0; // 2 - interlace flag
+        // 3 - sort flag
+        // 4-5 - reserved
+        mLctSize = 2 << (packed & 7); // 6-8 - local color table size
+        if (mLctFlag) {
+            mLct = readColorTable(mLctSize); // read table
+            mAct = mLct; // make local table active
+        } else {
+            mAct = mGct; // make global table active
+            if (mBgIndex == mTransIndex) {
+                mBgColor = 0;
+            }
+        }
+        int save = 0;
+        if (mTransparency) {
+            save = mAct[mTransIndex];
+            mAct[mTransIndex] = 0; // set transparent color if specified
+        }
+        if (mAct == null) {
+            mStatus = STATUS_FORMAT_ERROR; // no color table defined
+        }
+        if (err()) {
+            return;
+        }
+        try {
+            decodeImageData(); // decode pixel data
+            skip();
+            if (err()) {
+                return;
+            }
+            mFrameCount++;
+            // create new image to receive frame data
+            mImage = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_4444);
+            // createImage(mWidth, mHeight);
+            setPixels(); // transfer pixel data to image
+            if (mGifFrame == null) {
+                mGifFrame = new GifFrame(mImage, mDelay, mDispose);
+                mCurrentFrame = mGifFrame;
+            } else {
+                GifFrame f = mGifFrame;
+                while (f.mNextFrame != null) {
+                    f = f.mNextFrame;
+                }
+                f.mNextFrame = new GifFrame(mImage, mDelay, mDispose);
+            }
+            // frames.addElement(new GifFrame(image, delay)); // add image to
+            // frame
+            // list
+            if (mTransparency) {
+                mAct[mTransIndex] = save;
+            }
+            resetFrame();
+            if (mGifAction != null) {
+                mGifAction.parseOk(true, mFrameCount);
+            }
+        } catch (OutOfMemoryError e) {
+            Log.e("GifDecoder", ">>> log  : " + e.toString());
+            e.printStackTrace();
+        }
+    }
+
+    private void readLSD() {
+        // logical screen size
+        mWidth = readShort();
+        mHeight = readShort();
+        // packed fields
+        int packed = read();
+        mGctFlag = (packed & 0x80) != 0; // 1 : global color table flag
+        // 2-4 : color resolution
+        // 5 : gct sort flag
+        mGctSize = 2 << (packed & 7); // 6-8 : gct size
+        mBgIndex = read(); // background color index
+        mPixelAspect = read(); // pixel aspect ratio
+    }
+
+    private void readNetscapeExt() {
+        do {
+            readBlock();
+            if (mBlock[0] == 1) {
+                // loop count sub-block
+                int b1 = ((int) mBlock[1]) & 0xff;
+                int b2 = ((int) mBlock[2]) & 0xff;
+                mLoopCount = (b2 << 8) | b1;
+            }
+        } while ((mBlockSize > 0) && !err());
+    }
+
+    private int readShort() {
+        // read 16-bit value, LSB first
+        return read() | (read() << 8);
+    }
+
+    private void resetFrame() {
+        mLastDispose = mDispose;
+        mLrx = mIx;
+        mLry = mIy;
+        mLrw = mIw;
+        mLrh = mIh;
+        mLastImage = mImage;
+        mLastBgColor = mBgColor;
+        mDispose = 0;
+        mTransparency = false;
+        mDelay = 0;
+        mLct = null;
+    }
+
+    /**
+     * Skips variable length blocks up to and including next zero length block.
+     */
+    private void skip() {
+        do {
+            readBlock();
+        } while ((mBlockSize > 0) && !err());
+    }
+
+    private void freeFrame() {
+        GifFrame fg = mGifFrame;
+        while (fg != null) {
+            if (fg.mImage != null) {
+                fg.mImage.recycle();
+            }
+            fg.mImage = null;
+            fg = null;
+            mGifFrame = mGifFrame.mNextFrame;
+            fg = mGifFrame;
+        }
+    }
+
+    private void freeIS() {
+        if (mIS != null) {
+            try {
+                mIS.close();
+            } catch (Exception ex) {
+                ex.printStackTrace();
+            }
+            mIS = null;
+        }
+        mGifData = null;
+    }
+
+    private void freeImage() {
+        if (mImage != null) {
+            mImage.recycle();
+            mImage = null;
+        }
+        if (mLastImage != null) {
+            mLastImage.recycle();
+            mLastImage = null;
+        }
+    }
+}
diff --git a/src/com/android/gallery3d/util/GifFrame.java b/src/com/android/gallery3d/util/GifFrame.java
new file mode 100755
index 0000000..87d58a4
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifFrame.java
@@ -0,0 +1,17 @@
+package com.android.gallery3d.util;
+
+import android.graphics.Bitmap;
+
+public class GifFrame {
+
+    public Bitmap    mImage;
+    public int       mDelayInMs;  //in milliseconds
+    public int       mDispose;
+    public GifFrame  mNextFrame = null;
+
+    public GifFrame(Bitmap bitmap, int delay, int dispose) {
+        mImage = bitmap;
+        mDelayInMs = delay;
+        mDispose = dispose;
+    }
+}
diff --git a/src/com/android/gallery3d/util/GifRequest.java b/src/com/android/gallery3d/util/GifRequest.java
new file mode 100755
index 0000000..ea928ad
--- /dev/null
+++ b/src/com/android/gallery3d/util/GifRequest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package com.android.gallery3d.util;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.gallery3d.util.ThreadPool.Job;
+import com.android.gallery3d.util.ThreadPool.JobContext;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+
+public class GifRequest implements Job<GifDecoder> {
+
+    private static final String TAG = "GifRequest";
+    Uri itemUri;
+    Context mContext;
+
+    public GifRequest(Uri uri, Context context) {
+        itemUri = uri;
+        mContext = context;
+    }
+
+    private InputStream getInputStream(Uri uri) {
+        ContentResolver cr = mContext.getContentResolver();
+        InputStream input = null;
+        try {
+            input = cr.openInputStream(uri);
+        } catch (IOException e) {
+            Log.e(TAG, "catch exception:" + e);
+        }
+        return input;
+    }
+
+    @Override
+    public GifDecoder run(JobContext jc) {
+        InputStream input = getInputStream(itemUri);
+        if (input != null) {
+            return new GifDecoder(getInputStream(itemUri), null);
+        } else {
+            return null;
+        }
+    }
+
+
+}
+
diff --git a/src/com/android/gallery3d/util/ViewGifImage.java b/src/com/android/gallery3d/util/ViewGifImage.java
new file mode 100755
index 0000000..a85af56
--- /dev/null
+++ b/src/com/android/gallery3d/util/ViewGifImage.java
@@ -0,0 +1,67 @@
+package com.android.gallery3d.util;
+
+import org.codeaurora.gallery.R;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+public class ViewGifImage extends Activity {
+    private static final String TAG       = "ViewGifImage";
+    public  static final String VIEW_GIF_ACTION = "com.android.gallery3d.VIEW_GIF";
+
+    public  static DisplayMetrics mDM;
+
+    private ImageView mGifView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.view_gif_image);
+        mDM = new DisplayMetrics();
+        getWindowManager().getDefaultDisplay().getMetrics(mDM);
+        if (getIntent().getAction() != null
+                && getIntent().getAction().equals(VIEW_GIF_ACTION)) {
+            Uri gifUri = getIntent().getData();
+            showGifPicture(gifUri);
+        }
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        finish();
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mGifView != null && mGifView instanceof GIFView) {
+            ((GIFView) mGifView).freeMemory();
+            mGifView = null;
+        }
+        super.onDestroy();
+    }
+
+    private void showGifPicture(Uri uri) {
+        mGifView = new GIFView(this);
+        ((LinearLayout) findViewById(R.id.image_absoluteLayout)).addView(mGifView,
+                new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        if (((GIFView) mGifView).setDrawable(uri)) return;
+        
+        finish();
+
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        getWindowManager().getDefaultDisplay().getMetrics(mDM);
+        super.onConfigurationChanged(newConfig);
+    }
+}
diff --git a/src/com/android/photos/AlbumFragment.java b/src/com/android/photos/AlbumFragment.java
index 886ca68..312b295 100644
--- a/src/com/android/photos/AlbumFragment.java
+++ b/src/com/android/photos/AlbumFragment.java
@@ -30,7 +30,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.GalleryActivity;
 import com.android.photos.adapters.PhotoThumbnailAdapter;
 import com.android.photos.data.PhotoSetLoader;
diff --git a/src/com/android/photos/AlbumSetFragment.java b/src/com/android/photos/AlbumSetFragment.java
index bc5289e..69025ac 100644
--- a/src/com/android/photos/AlbumSetFragment.java
+++ b/src/com/android/photos/AlbumSetFragment.java
@@ -29,7 +29,7 @@
 import android.view.ViewGroup;
 import android.widget.GridView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.photos.adapters.AlbumSetCursorAdapter;
 import com.android.photos.data.AlbumSetLoader;
 import com.android.photos.shims.LoaderCompatShim;
diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java
index 51c78d6..a02adac 100644
--- a/src/com/android/photos/GalleryActivity.java
+++ b/src/com/android/photos/GalleryActivity.java
@@ -29,7 +29,7 @@
 import android.view.MenuItem;
 import android.view.ViewGroup;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 
diff --git a/src/com/android/photos/MultiChoiceManager.java b/src/com/android/photos/MultiChoiceManager.java
index 49519ca..137898c 100644
--- a/src/com/android/photos/MultiChoiceManager.java
+++ b/src/com/android/photos/MultiChoiceManager.java
@@ -28,10 +28,8 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.widget.AbsListView.MultiChoiceModeListener;
-import android.widget.ShareActionProvider;
-import android.widget.ShareActionProvider.OnShareTargetSelectedListener;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.gallery3d.app.TrimVideo;
 import com.android.gallery3d.data.MediaObject;
 import com.android.gallery3d.filtershow.FilterShowActivity;
@@ -42,7 +40,7 @@
 import java.util.List;
 
 public class MultiChoiceManager implements MultiChoiceModeListener,
-    OnShareTargetSelectedListener, SelectionManager.SelectedUriSource {
+    SelectionManager.SelectedUriSource {
 
     public interface Provider {
         public MultiChoiceManager getMultiChoiceManager();
@@ -61,7 +59,6 @@
     }
 
     private SelectionManager mSelectionManager;
-    private ShareActionProvider mShareActionProvider;
     private ActionMode mActionMode;
     private Context mContext;
     private Delegate mDelegate;
@@ -122,7 +119,7 @@
             }
         }
 
-        mSelectionManager.onItemSelectedStateChanged(mShareActionProvider,
+        mSelectionManager.onItemSelectedStateChanged(
                 mDelegate.getItemMediaType(item),
                 supported,
                 checked);
@@ -155,8 +152,21 @@
         MenuInflater inflater = mode.getMenuInflater();
         inflater.inflate(R.menu.gallery_multiselect, menu);
         MenuItem menuItem = menu.findItem(R.id.menu_share);
-        mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
-        mShareActionProvider.setOnShareTargetSelectedListener(this);
+        if (menuItem != null) {
+            menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+                @Override
+                public boolean onMenuItemClick(MenuItem item) {
+                    mActionMode.finish();
+                    Intent shareIntent = mSelectionManager.getShareIntent();
+                    if (shareIntent != null) {
+                        Intent intent = Intent.createChooser(shareIntent, null);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        mContext.startActivity(intent);
+                    }
+                    return true;
+                }
+            });
+        }
         updateSelectedTitle(mode);
         return true;
     }
@@ -169,7 +179,6 @@
         mSelectedShareableUrisArray = new ArrayList<Uri>();
         mSelectionManager.onClearSelection();
         mSelectionManager.setSelectedUriSource(null);
-        mShareActionProvider = null;
         mActionMode = null;
     }
 
@@ -179,12 +188,6 @@
         return false;
     }
 
-    @Override
-    public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) {
-        mActionMode.finish();
-        return false;
-    }
-
     private static class BulkDeleteTask extends AsyncTask<Void, Void, Void> {
         private Delegate mDelegate;
         private List<Object> mPaths;
diff --git a/src/com/android/photos/MultiSelectGridFragment.java b/src/com/android/photos/MultiSelectGridFragment.java
index dda9fe4..ccf7e0e 100644
--- a/src/com/android/photos/MultiSelectGridFragment.java
+++ b/src/com/android/photos/MultiSelectGridFragment.java
@@ -30,7 +30,7 @@
 import android.widget.ListAdapter;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 public abstract class MultiSelectGridFragment extends Fragment
         implements MultiChoiceManager.Delegate, AdapterView.OnItemClickListener {
diff --git a/src/com/android/photos/SelectionManager.java b/src/com/android/photos/SelectionManager.java
index 9bfb9be..1ab7691 100644
--- a/src/com/android/photos/SelectionManager.java
+++ b/src/com/android/photos/SelectionManager.java
@@ -23,7 +23,6 @@
 import android.nfc.NfcAdapter.CreateBeamUrisCallback;
 import android.nfc.NfcEvent;
 import android.provider.MediaStore.Files.FileColumns;
-import android.widget.ShareActionProvider;
 
 import com.android.gallery3d.common.ApiHelper;
 import com.android.gallery3d.data.MediaObject;
@@ -74,8 +73,8 @@
 
     private ArrayList<Uri> mCachedShareableUris = null;
 
-    public void onItemSelectedStateChanged(ShareActionProvider share,
-            int itemType, int itemSupportedOperations, boolean selected) {
+    public void onItemSelectedStateChanged(int itemType, int itemSupportedOperations,
+            boolean selected) {
         int increment = selected ? 1 : -1;
 
         mSelectedTotalCount += increment;
@@ -132,7 +131,6 @@
                 }
             }
         }
-        share.setShareIntent(mShareIntent);
     }
 
     public int getSupportedOperations() {
@@ -181,4 +179,8 @@
         mShareIntent.removeExtra(Intent.EXTRA_STREAM);
         mShareIntent.setAction(null).setType(null);
     }
+
+    public Intent getShareIntent() {
+        return mShareIntent;
+    }
 }
diff --git a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
index ab99cde..58a78f7 100644
--- a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
+++ b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java
@@ -28,7 +28,7 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.photos.data.AlbumSetLoader;
 import com.android.photos.shims.LoaderCompatShim;
 
diff --git a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
index 1190b8c..1c124d9 100644
--- a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
+++ b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java
@@ -25,7 +25,7 @@
 import android.widget.CursorAdapter;
 import android.widget.ImageView;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 import com.android.photos.data.PhotoSetLoader;
 import com.android.photos.shims.LoaderCompatShim;
 import com.android.photos.views.GalleryThumbnailView.GalleryThumbnailAdapter;
diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/src/com/android/photos/views/TiledImageRenderer.java
index e3b7f38..a4a8d48 100644
--- a/src/com/android/photos/views/TiledImageRenderer.java
+++ b/src/com/android/photos/views/TiledImageRenderer.java
@@ -159,7 +159,7 @@
     }
 
     public static int suggestedTileSize(Context context) {
-        return isHighResolution(context) ? 512 : 256;
+        return isHighResolution(context) ? 2048 : 1024;
     }
 
     private static boolean isHighResolution(Context context) {
diff --git a/src/com/thundersoft/hz/selfportrait/detect/FaceDetect.java b/src/com/thundersoft/hz/selfportrait/detect/FaceDetect.java
new file mode 100644
index 0000000..a37ca09
--- /dev/null
+++ b/src/com/thundersoft/hz/selfportrait/detect/FaceDetect.java
@@ -0,0 +1,104 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.thundersoft.hz.selfportrait.detect;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.util.Log;
+
+public class FaceDetect {
+    private static final String TAG = "FaceDetect";
+
+    private long mHandle = 0;
+    private static boolean mLibLoaded;
+
+    static {
+        try {
+            System.loadLibrary("ts_detected_face_jni");
+            mLibLoaded = true;
+        } catch (UnsatisfiedLinkError e) {
+            e.printStackTrace();
+            mLibLoaded = false;
+            Log.e(TAG, "ts_detected_face_jni library not found!");
+        }
+    }
+
+    /**
+     * initialize method,MUST called at first time.
+     */
+    public void initialize() {
+        try {
+            mHandle = native_create();
+        } catch (UnsatisfiedLinkError e) {
+            e.printStackTrace();
+            Log.e(TAG, "could not link native handle for ts_detected_face_jni library!");
+        }
+    }
+
+    public boolean isLibLoaded() {
+        return mLibLoaded;
+    }
+
+    /**
+     * uninitialize method,MUST called at last time.
+     */
+
+    public void uninitialize() {
+        if (mHandle != 0) {
+            native_destroy(mHandle);
+        }
+    }
+
+    /**
+     * dectectFeatures method,MUST called after initialize method and before
+     * uninitialize method.
+     *
+     * @param bmp, Android Bitmap instance,MUST not null.
+     * @return FaceInfo array if success, otherwise return null.
+     */
+    public FaceInfo[] dectectFeatures(Bitmap bmp) {
+        // check if the initialization failed
+        if (mHandle == 0) {
+            return null;
+        }
+
+        int count = 0;
+        try {
+            count = native_detect(mHandle, bmp);
+        } catch (UnsatisfiedLinkError e) {
+            e.printStackTrace();
+            Log.e(TAG, "could not link native handle for ts_detected_face_jni library!");
+        }
+        if (count < 1) {
+            return null;
+        }
+        FaceInfo[] res = new FaceInfo[count];
+        for (int i = 0; i < count; i++) {
+            FaceInfo face = new FaceInfo();
+            native_face_info(mHandle, i, face.face, face.eye1, face.eye2, face.mouth);
+            res[i] = face;
+        }
+        return res;
+    }
+
+    private static native long native_create();
+    private static native void native_destroy(long handle);
+    private static native int native_detect(long handle, Bitmap bmp);
+    private static native int native_face_info(long handle, int index, Rect face, Rect eye1,
+            Rect eye2, Rect mouth);
+}
diff --git a/src/com/thundersoft/hz/selfportrait/detect/FaceInfo.java b/src/com/thundersoft/hz/selfportrait/detect/FaceInfo.java
new file mode 100644
index 0000000..eee51f7
--- /dev/null
+++ b/src/com/thundersoft/hz/selfportrait/detect/FaceInfo.java
@@ -0,0 +1,39 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.thundersoft.hz.selfportrait.detect;
+
+import android.graphics.Rect;
+
+public class FaceInfo {
+    /**
+     * face rectangle
+     */
+    public Rect face = new Rect();
+    /**
+     * left eye rectangle
+     */
+    public Rect eye1 = new Rect();
+    /**
+     * right eye rectangle
+     */
+    public Rect eye2 = new Rect();
+    /**
+     * mount rectangle
+     */
+    public Rect mouth = new Rect();
+}
diff --git a/src/com/thundersoft/hz/selfportrait/makeup/engine/MakeupEngine.java b/src/com/thundersoft/hz/selfportrait/makeup/engine/MakeupEngine.java
new file mode 100644
index 0000000..1ddb238
--- /dev/null
+++ b/src/com/thundersoft/hz/selfportrait/makeup/engine/MakeupEngine.java
@@ -0,0 +1,83 @@
+/*
+* Copyright (C) 2014,2015 Thundersoft Corporation
+* All rights Reserved
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.thundersoft.hz.selfportrait.makeup.engine;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.util.Log;
+
+public class MakeupEngine {
+    static {
+        try {
+            System.loadLibrary("ts_face_beautify_jni");
+            mLibLoaded = true;
+        } catch (UnsatisfiedLinkError e) {
+            e.printStackTrace();
+            mLibLoaded = false;
+            Log.e(MakeupEngine.class.getName(), "ts_face_beautify_jni library not found!");
+        }
+    }
+
+    private static boolean mLibLoaded;
+    private static MakeupEngine mInstance;
+
+    private MakeupEngine() {
+
+    }
+
+    public boolean isLibLoaded() {
+        return mLibLoaded;
+    }
+
+    public static MakeupEngine getMakeupObj() {
+        if(mInstance == null) {
+            mInstance = new MakeupEngine();
+        }
+
+        return mInstance;
+    }
+
+    /**
+     * FUNCTION: doProcessBeautify
+     * Do process face region clean and whiten.
+     * @param inBitmap, the Bitmap instance which have face region, MUST not null.
+     * @param outBitmap, the result of process, MUST not null.
+     * @param frameWidth,frameHeight, the size of inBitmap.
+     * @param faceRect, the face region in inBitmap.
+     * @param cleanLevel, the level of clean.(0-100)
+     * @param whiteLevel, the level of white.(0-100)
+     */
+    public static native boolean doProcessBeautify(Bitmap inBitmap, Bitmap outBitmap, int frameWidth, int frameHeight,
+            Rect faceRect, int cleanLevel, int beautyLevel);
+
+    /**
+     * FUNCTION: doWarpFace
+     * Do process face region warp and big eye.
+     * @param inBitmap, the Bitmap instance which have face region, MUST not null.
+     * @param outBitmap, the result of process, MUST not null.
+     * @param frameWidth, the size of inBitmap.
+     * @param frameHeight, the size of inBitmap.
+     * @param leftEye, the left eye rectangle
+     * @param rightEye, the right eye rectangle
+     * @param mouth, the mouth rectangle
+     * @param bigEyeLevel, the level of big eye.(0-100)
+     * @param trimFaceLevel, the level of trim face.(0-100)
+     */
+    public static native boolean doWarpFace(Bitmap inBitmap, Bitmap outBitmap, int frameWidth, int frameHeight,
+            Rect leftEye, Rect rightEye, Rect mouth, int bigEyeLevel, int trimFaceLevel);
+}
diff --git a/src/org/codeaurora/gallery3d/ext/ActivityHooker.java b/src/org/codeaurora/gallery3d/ext/ActivityHooker.java
new file mode 100644
index 0000000..65761ff
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/ActivityHooker.java
@@ -0,0 +1,96 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Default implemention class of IActivityHooker.
+ */
+public class ActivityHooker implements IActivityHooker {
+
+    private static final int MENU_MAX_NUMBER = 100;
+    private static int sMenuId = 1;
+    private int mMenuId;
+    private static Object sMenuLock = new Object();
+    private Activity mContext;
+    private Intent mIntent;
+
+    public ActivityHooker() {
+        synchronized (sMenuLock) {
+            sMenuId++;
+            mMenuId = sMenuId * MENU_MAX_NUMBER;
+        }
+    }
+
+    @Override
+    public int getMenuActivityId(int id) {
+        return mMenuId + id;
+    };
+
+    @Override
+    public int getMenuOriginalId(int id) {
+        return id - mMenuId;
+    }
+
+    @Override
+    public void init(Activity context, Intent intent) {
+        mContext = context;
+        mIntent = intent;
+    }
+
+    @Override
+    public Activity getContext() {
+        return mContext;
+    }
+
+    @Override
+    public Intent getIntent() {
+        return mIntent;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+    }
+
+    @Override
+    public void onStart() {
+    }
+
+    @Override
+    public void onResume() {
+    }
+
+    @Override
+    public void onPause() {
+    }
+
+    @Override
+    public void onStop() {
+    }
+
+    @Override
+    public void onDestroy() {
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        return false;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        return false;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        return false;
+    }
+
+    @Override
+    public void setParameter(String key, Object value) {
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/ext/ActivityHookerGroup.java b/src/org/codeaurora/gallery3d/ext/ActivityHookerGroup.java
new file mode 100644
index 0000000..4bf8616
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/ActivityHookerGroup.java
@@ -0,0 +1,150 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import java.util.ArrayList;
+
+/**
+ * The composite pattern class. It will deliver every action to its leaf
+ * hookers.
+ */
+public class ActivityHookerGroup extends ActivityHooker {
+    private ArrayList<IActivityHooker> mHooks = new ArrayList<IActivityHooker>();
+
+    /**
+     * Add hooker to current group.
+     *
+     * @param hooker
+     * @return
+     */
+    public boolean addHooker(IActivityHooker hooker) {
+        return mHooks.add(hooker);
+    }
+
+    /**
+     * Remove hooker from current group.
+     *
+     * @param hooker
+     * @return
+     */
+    public boolean removeHooker(IActivityHooker hooker) {
+        return mHooks.remove(hooker);
+    }
+
+    /**
+     * Get hooker of requested location.
+     *
+     * @param index
+     * @return
+     */
+    public IActivityHooker getHooker(int index) {
+        return mHooks.get(index);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        for (IActivityHooker hook : mHooks) {
+            hook.onCreate(savedInstanceState);
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        for (IActivityHooker hook : mHooks) {
+            hook.onStart();
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        for (IActivityHooker hook : mHooks) {
+            hook.onResume();
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        for (IActivityHooker hook : mHooks) {
+            hook.onPause();
+        }
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        for (IActivityHooker hook : mHooks) {
+            hook.onStop();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        for (IActivityHooker hook : mHooks) {
+            hook.onDestroy();
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        boolean handle = false;
+        for (IActivityHooker hook : mHooks) {
+            boolean one = hook.onCreateOptionsMenu(menu);
+            if (!handle) {
+                handle = one;
+            }
+        }
+        return handle;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        boolean handle = false;
+        for (IActivityHooker hook : mHooks) {
+            boolean one = hook.onPrepareOptionsMenu(menu);
+            if (!handle) {
+                handle = one;
+            }
+        }
+        return handle;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        super.onOptionsItemSelected(item);
+        boolean handle = false;
+        for (IActivityHooker hook : mHooks) {
+            boolean one = hook.onOptionsItemSelected(item);
+            if (!handle) {
+                handle = one;
+            }
+        }
+        return handle;
+    }
+
+    @Override
+    public void setParameter(String key, Object value) {
+        super.setParameter(key, value);
+        for (IActivityHooker hook : mHooks) {
+            hook.setParameter(key, value);
+        }
+    }
+
+    @Override
+    public void init(Activity context, Intent intent) {
+        super.init(context, intent);
+        for (IActivityHooker hook : mHooks) {
+            hook.init(context, intent);
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/ext/IActivityHooker.java b/src/org/codeaurora/gallery3d/ext/IActivityHooker.java
new file mode 100644
index 0000000..a837996
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IActivityHooker.java
@@ -0,0 +1,128 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Activity action hooker class. Host app's activity will call this hooker's
+ * functions in its lifecycle. For example:
+ * HostActivity.onCreate()-->hooker.onCreate(). But void init(Activity context,
+ * Intent intent) will be called before other functions. <br/>
+ * IActivityHooker objects may show menus, but we should give a unique menu id
+ * to every menus. Hooker can call getMenuActivityId(int) to get a global unique
+ * menu id to be used in menu.add(), and can call getMenuOriginalId(int) to get
+ * the original menu id. the example: class Hooker implements IActivityHooker {
+ * private static final int MENU_EXAMPLE = 1;
+ *
+ * @Override public boolean onCreateOptionsMenu(Menu menu) {
+ *           super.onCreateOptionsMenu(menu); menu.add(0,
+ *           getMenuActivityId(MENU_EXAMPLE), 0, android.R.string.ok); return
+ *           true; }
+ * @Override public boolean onOptionsItemSelected(MenuItem item) {
+ *           switch(getMenuOriginalId(item.getItemId())) { case MENU_EXAMPLE:
+ *           //do something return true; default: return false; } } }
+ */
+public interface IActivityHooker {
+    /**
+     * Will be called in Host Activity.onCreate(Bundle savedInstanceState)
+     * @param savedInstanceState
+     */
+    void onCreate(Bundle savedInstanceState);
+    /**
+     * Will be called in Host Activity.onStart()
+     */
+    void onStart();
+    /**
+     * Will be called in Host Activity.onStop()
+     */
+    void onStop();
+    /**
+     * Will be called in Host Activity.onPause()
+     */
+    void onPause();
+    /**
+     * Will be called in Host Activity.onResume()
+     */
+    void onResume();
+    /**
+     * Will be called in Host Activity.onDestroy()
+     */
+    void onDestroy();
+    /**
+     * Will be called in Host Activity.onCreateOptionsMenu(Menu menu)
+     * @param menu
+     * @return
+     */
+    /**
+     * Will be called in Host Activity.onCreateOptionsMenu(Menu menu)
+     *
+     * @param menu
+     * @return
+     */
+    boolean onCreateOptionsMenu(Menu menu);
+
+    /**
+     * Will be called in Host Activity.onPrepareOptionsMenu(Menu menu)
+     *
+     * @param menu
+     * @return
+     */
+    boolean onPrepareOptionsMenu(Menu menu);
+
+    /**
+     * Will be called in Host Activity.onOptionsItemSelected(MenuItem item)
+     *
+     * @param item
+     * @return
+     */
+    boolean onOptionsItemSelected(MenuItem item);
+
+    /**
+     * Should be called before any other functions.
+     *
+     * @param context
+     * @param intent
+     */
+    void init(Activity context, Intent intent);
+
+    /**
+     * @return return activity set by init(Activity context, Intent intent)
+     */
+    Activity getContext();
+
+    /**
+     * @return return intent set by init(Activity context, Intent intent)
+     */
+    Intent getIntent();
+
+    /**
+     * IActivityHooker objects may show menus, but we should give a unique menu
+     * id to every menus. Hooker can call this function to get a global unique
+     * menu id to be used in menu.add()
+     *
+     * @param id
+     * @return
+     */
+    int getMenuActivityId(int id);
+
+    /**
+     * When onOptionsItemSelected is called, we can get menu's id from
+     * parameter. You can get the original menu id by calling this function.
+     *
+     * @param id
+     * @return
+     */
+    int getMenuOriginalId(int id);
+
+    /**
+     * Host activity will call this function to set parameter to hooker
+     * activity.
+     *
+     * @param key
+     * @param value
+     */
+    void setParameter(String key, Object value);
+}
diff --git a/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java
new file mode 100644
index 0000000..73bef5e
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IContrllerOverlayExt.java
@@ -0,0 +1,50 @@
+package org.codeaurora.gallery3d.ext;
+/**
+ * Controller overlay extension interface.
+ */
+public interface IContrllerOverlayExt {
+    /**
+     * Show buffering state.
+     * @param what
+     */
+    void showBuffering(int what);
+    /**
+     * Clear buffering state.
+     */
+    void clearBuffering();
+    /**
+     * Show re-connecting state.
+     * @param times
+     */
+    void showReconnecting(int times);
+    /**
+     * Show re-connecting error for connecting fail error.
+     */
+    void showReconnectingError();
+    /**
+     * Show playing info or not.
+     * @param liveStreaming true means showing playing info, otherwise doesn't show playing info.
+     */
+    void setPlayingInfo(boolean liveStreaming);
+    /**
+     * Indicates whether current video can be paused or not.
+     * @param canPause
+     */
+    void setCanPause(boolean canPause);
+    /**
+     * Indicates whether thumb can be scrubbed or not. 
+     * @param enable
+     */
+    void setCanScrubbing(boolean enable);
+    /**
+     * Always show bottmon panel or not.
+     * @param alwaysShow
+     * @param foreShow
+     */
+    void setBottomPanel(boolean alwaysShow, boolean foreShow);
+    /**
+     * Is playing end or not.
+     * @return
+     */
+    boolean isPlayingEnd();
+}
diff --git a/src/org/codeaurora/gallery3d/ext/IMovieItem.java b/src/org/codeaurora/gallery3d/ext/IMovieItem.java
new file mode 100644
index 0000000..dece4e8
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IMovieItem.java
@@ -0,0 +1,66 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.net.Uri;
+
+/**
+ * Movie info class
+ */
+public interface IMovieItem {
+    /**
+     * @return movie Uri, it's may be not the original Uri.
+     */
+    Uri getUri();
+
+    /**
+     * @return MIME type of video
+     */
+    String getMimeType();
+
+    /**
+     * @return title of video
+     */
+    String getTitle();
+
+    /**
+     * @return whether error occured or not.
+     */
+    boolean getError();
+
+    /**
+     * set title of video
+     *
+     * @param title
+     */
+    void setTitle(String title);
+
+    /**
+     * set video Uri
+     *
+     * @param uri
+     */
+    void setUri(Uri uri);
+
+    /**
+     * Set MIME type of video
+     *
+     * @param mimeType
+     */
+    void setMimeType(String mimeType);
+
+    /**
+     * Set error occured flag
+     */
+    void setError();
+
+    /**
+     * @return return original Uri of video.
+     */
+    Uri getOriginalUri();
+
+    /**
+     * Set video original Uri.
+     *
+     * @param uri
+     */
+    void setOriginalUri(Uri uri);
+}
diff --git a/src/org/codeaurora/gallery3d/ext/IMovieList.java b/src/org/codeaurora/gallery3d/ext/IMovieList.java
new file mode 100644
index 0000000..404d24c
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IMovieList.java
@@ -0,0 +1,46 @@
+package org.codeaurora.gallery3d.ext;
+/**
+ * Movie list extension interface
+ */
+public interface IMovieList {
+    /**
+     * Add movie item to list.
+     * @param item
+     */
+    void add(IMovieItem item);
+    /**
+     * Get the item index of list
+     * @param item
+     * @return
+     */
+    int index(IMovieItem item);
+    /**
+     * 
+     * @return list size
+     */
+    int size();
+    /**
+     * 
+     * @param item
+     * @return next item of current item
+     */
+    IMovieItem getNext(IMovieItem item);
+    /**
+     * 
+     * @param item
+     * @return previous item of current item
+     */
+    IMovieItem getPrevious(IMovieItem item);
+    /**
+     * Is first item in list
+     * @param item
+     * @return
+     */
+    boolean isFirst(IMovieItem item);
+    /**
+     * Is last item in list.
+     * @param item
+     * @return
+     */
+    boolean isLast(IMovieItem item);
+}
\ No newline at end of file
diff --git a/src/org/codeaurora/gallery3d/ext/IMovieListLoader.java b/src/org/codeaurora/gallery3d/ext/IMovieListLoader.java
new file mode 100644
index 0000000..fe59998
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IMovieListLoader.java
@@ -0,0 +1,51 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+public interface IMovieListLoader {
+    /**
+     * Load all video list or not.[boolean]
+     * "yes" means load all videos in all storages.
+     * "false" means load videos located in current video's folder.
+     */
+    String EXTRA_ALL_VIDEO_FOLDER = "org.codeaurora.intent.extra.ALL_VIDEO_FOLDER";
+    /**
+     * Video list order by column name.[String]
+     */
+    String EXTRA_ORDERBY = "org.codeaurora.intent.extra.VIDEO_LIST_ORDERBY";
+    /**
+     * Enable video list or not.[boolean]
+     */
+    String EXTRA_ENABLE_VIDEO_LIST = "org.codeaurora.intent.extra.ENABLE_VIDEO_LIST";
+    /**
+     * Loader listener interface
+     */
+    public interface LoaderListener {
+        /**
+         * Will be called after movie list loaded.
+         * @param movieList
+         */
+        void onListLoaded(IMovieList movieList);
+    }
+    /**
+     * Build the movie list from current item.
+     * @param context
+     * @param intent
+     * @param l
+     * @param item
+     */
+    void fillVideoList(Activity context, Intent intent, LoaderListener l, IMovieItem item);
+    /**
+     * enable video list or not.
+     * @param intent
+     * @return
+     */
+    boolean isEnabledVideoList(Intent intent);
+    /**
+     * Cancel current loading process.
+     */
+    void cancelList();
+
+}
diff --git a/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java b/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java
new file mode 100644
index 0000000..32d400b
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/IMoviePlayer.java
@@ -0,0 +1,42 @@
+package org.codeaurora.gallery3d.ext;
+
+public interface IMoviePlayer {
+
+    /**
+     * add new bookmark Uri.
+     */
+    void addBookmark();
+
+    /**
+     * Loop current video.
+     *
+     * @param loop
+     */
+    void setLoop(boolean loop);
+
+    /**
+     * Loop current video or not
+     *
+     * @return
+     */
+    boolean getLoop();
+
+    /**
+     * Can stop current video or not.
+     *
+     * @return
+     */
+    boolean canStop();
+
+    /**
+     * Stop current video.
+     */
+    void stopVideo();
+
+    /**
+     * start current item and stop playing video.
+     *
+     * @param item
+     */
+    void startNextVideo(IMovieItem item);
+}
diff --git a/src/org/codeaurora/gallery3d/ext/MovieItem.java b/src/org/codeaurora/gallery3d/ext/MovieItem.java
new file mode 100644
index 0000000..56afdda
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/MovieItem.java
@@ -0,0 +1,115 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.net.Uri;
+import android.provider.MediaStore;
+
+public class MovieItem implements IMovieItem {
+    private static final String TAG = "MovieItem";
+    private static final boolean LOG = false;
+
+    private Uri mUri;
+    private String mMimeType;
+    private String mTitle;
+    private boolean mError;
+    // private int mStereoType;
+    private Uri mOriginal;
+
+    private static final int STREO_TYPE_2D = 1;
+
+    public MovieItem(Uri uri, String mimeType, String title, int stereoType) {
+        mUri = uri;
+        mMimeType = mimeType;
+        mTitle = title;
+        // mStereoType = stereoType;
+        mOriginal = uri;
+    }
+
+    public MovieItem(String uri, String mimeType, String title, int stereoType) {
+        this(Uri.parse(uri), mimeType, title, stereoType);
+    }
+
+    public MovieItem(Uri uri, String mimeType, String title) {
+        this(uri, mimeType, title, STREO_TYPE_2D);
+    }
+
+    public MovieItem(String uri, String mimeType, String title) {
+        this(Uri.parse(uri), mimeType, title);
+    }
+
+    @Override
+    public Uri getUri() {
+        return mUri;
+    }
+
+    @Override
+    public String getMimeType() {
+        return mMimeType;
+    }
+
+    @Override
+    public String getTitle() {
+        return mTitle;
+    }
+
+    @Override
+    public boolean getError() {
+        return mError;
+    }
+
+    // @Override
+    // public int getStereoType() {
+    // return mStereoType;
+    // }
+
+    public void setTitle(String title) {
+        mTitle = title;
+    }
+
+    @Override
+    public void setUri(Uri uri) {
+        mUri = uri;
+    }
+
+    @Override
+    public void setMimeType(String mimeType) {
+        mMimeType = mimeType;
+    }
+
+    // @Override
+    // public void setStereoType(int stereoType) {
+    // mStereoType = stereoType;
+    // }
+
+    @Override
+    public void setError() {
+        mError = true;
+    }
+
+    @Override
+    public Uri getOriginalUri() {
+        return mOriginal;
+    }
+
+    @Override
+    public void setOriginalUri(Uri uri) {
+        mOriginal = uri;
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder().append("MovieItem(uri=")
+                .append(mUri)
+                .append(", mime=")
+                .append(mMimeType)
+                .append(", title=")
+                .append(mTitle)
+                .append(", error=")
+                .append(mError)
+                // .append(", support3D=")
+                // .append(mStereoType)
+                .append(", mOriginal=")
+                .append(mOriginal)
+                .append(")")
+                .toString();
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/ext/MovieList.java b/src/org/codeaurora/gallery3d/ext/MovieList.java
new file mode 100644
index 0000000..ecb7f0d
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/MovieList.java
@@ -0,0 +1,72 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class MovieList implements IMovieList {
+    private static final String TAG = "MovieList";
+    private static final boolean LOG = false;
+    
+    private final ArrayList<IMovieItem> mItems = new ArrayList<IMovieItem>();
+    private static final int UNKNOWN = -1;
+    
+    @Override
+    public void add(IMovieItem item) {
+        if (LOG) {
+            Log.v(TAG, "add(" + item + ")");
+        }
+        mItems.add(item);
+    }
+    
+    @Override
+    public int index(IMovieItem item) {
+        int find = UNKNOWN;
+        int size = mItems.size();
+        for (int i = 0; i < size; i++) {
+            if (item == mItems.get(i)) {
+                find = i;
+                break;
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "index(" + item + ") return " + find);
+        }
+        return find;
+    }
+    
+    @Override
+    public int size() {
+        return mItems.size();
+    }
+    
+    @Override
+    public IMovieItem getNext(IMovieItem item) {
+        IMovieItem next = null;
+        int find = index(item);
+        if (find >= 0 && find < size() - 1) {
+            next = mItems.get(++find);
+        }
+        return next;
+    }
+    
+    @Override
+    public IMovieItem getPrevious(IMovieItem item) {
+        IMovieItem prev = null;
+        int find = index(item);
+        if (find > 0 && find < size()) {
+            prev = mItems.get(--find);
+        }
+        return prev;
+    }
+
+    @Override
+    public boolean isFirst(IMovieItem item) {
+        return getPrevious(item) == null;
+    }
+
+    @Override
+    public boolean isLast(IMovieItem item) {
+        return getNext(item) == null;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/ext/MovieListLoader.java b/src/org/codeaurora/gallery3d/ext/MovieListLoader.java
new file mode 100644
index 0000000..237d7e1
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/MovieListLoader.java
@@ -0,0 +1,274 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.util.Log;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+ * Movie list loader class. It will load videos from MediaProvider database.
+ * If MoviePlayer starting activity doesn't set any thing, default OrderBy will be used.
+ * Default OrderBy: MediaStore.Video.Media.DATE_TAKEN + " DESC, " + MediaStore.Video.Media._ID + " DESC ";
+ */
+public class MovieListLoader implements IMovieListLoader {  
+    private static final String TAG = "MovieListLoader";
+    private static final boolean LOG = false;
+    
+    private MovieListFetcherTask mListTask;
+    
+    @Override
+    public void fillVideoList(Activity activity, Intent intent, final LoaderListener l,
+            IMovieItem currentMovieItem) {
+
+        // determine if a video playlist has been passed in through the intent
+        // if a playlist does exist, use that
+        ArrayList<Uri> uris = intent.getParcelableArrayListExtra("EXTRA_FILE_LIST");
+        if (uris != null) {
+            final MovieList movieList = new MovieList();
+            ContentResolver cr = activity.getContentResolver();
+
+            for(Uri uri : uris) {
+                // add currentMovieItem in its proper place in the video playlist
+                // 'Next' and 'Previous' functionality in MovieListHooker is dependent on reference
+                // matching currentMovieItem
+                if (currentMovieItem.getOriginalUri().equals(uri)) {
+                    movieList.add(currentMovieItem);
+                    continue;
+                }
+
+                File videoFile = new File(uri.getPath());
+                movieList.add(new MovieItem(uri, cr.getType(uri), videoFile.getName()));
+            }
+
+            // notify callback on main thread
+            activity.runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    l.onListLoaded(movieList);
+                }
+            });
+
+            return;
+        }
+
+        // proceed with creating a playlist if one isn't found
+        boolean fetechAll = false;
+        if (intent.hasExtra(EXTRA_ALL_VIDEO_FOLDER)) {
+            fetechAll = intent.getBooleanExtra(EXTRA_ALL_VIDEO_FOLDER, false);
+        }
+        //default order by
+        String orderBy = MediaStore.Video.Media.DATE_TAKEN + " DESC, " + MediaStore.Video.Media._ID + " DESC ";
+        if (intent.hasExtra(EXTRA_ORDERBY)) {
+            orderBy = intent.getStringExtra(EXTRA_ORDERBY);
+        }
+        cancelList();
+        mListTask = new MovieListFetcherTask(activity, fetechAll, l, orderBy);
+        mListTask.execute(currentMovieItem);
+        if (LOG) {
+            Log.v(TAG, "fillVideoList() fetechAll=" + fetechAll + ", orderBy=" + orderBy);
+        }
+    }
+    
+    @Override
+    public boolean isEnabledVideoList(Intent intent) {
+        boolean enable = true;
+        if (intent != null && intent.hasExtra(EXTRA_ENABLE_VIDEO_LIST)) {
+            enable = intent.getBooleanExtra(EXTRA_ENABLE_VIDEO_LIST, true);
+        }
+        if (LOG) {
+            Log.v(TAG, "isEnabledVideoList() return " + enable);
+        }
+        return enable;
+    }
+    
+    @Override
+    public void cancelList() {
+        if (mListTask != null) {
+            mListTask.cancel(true);
+        }
+    }
+
+    private class MovieListFetcherTask extends AsyncTask<IMovieItem, Void, IMovieList> {
+        private static final String TAG = "MovieListFetcherTask";
+        private static final boolean LOG = false;
+        
+        // TODO comments by sunlei
+//        public static final String COLUMN_STEREO_TYPE = MediaStore.Video.Media.STEREO_TYPE;
+//        public static final String COLUMN_STEREO_TYPE = "STEREO_TYPE";
+        
+        private final ContentResolver mCr;
+        private final LoaderListener mFetecherListener;
+        private final boolean mFetechAll;
+        private final String mOrderBy;
+        
+        public MovieListFetcherTask(Context context, boolean fetechAll, LoaderListener l, String orderBy) {
+            mCr = context.getContentResolver();
+            mFetecherListener = l;
+            mFetechAll = fetechAll;
+            mOrderBy = orderBy;
+            if (LOG) {
+                Log.v(TAG, "MovieListFetcherTask() fetechAll=" + fetechAll + ", orderBy=" + orderBy);
+            }
+        }
+        
+        @Override
+        protected void onPostExecute(IMovieList params) {
+            if (LOG) {
+                Log.v(TAG, "onPostExecute() isCancelled()=" + isCancelled());
+            }
+            if (isCancelled()) {
+                return;
+            }
+            if (mFetecherListener != null) {
+                mFetecherListener.onListLoaded(params);
+            }
+        }
+        
+        @Override
+        protected IMovieList doInBackground(IMovieItem... params) {
+            if (LOG) {
+                Log.v(TAG, "doInBackground() begin");
+            }
+            if (params[0] == null) {
+                return null;
+            }
+            IMovieList movieList = null;
+            Uri uri = params[0].getUri();
+            String mime = params[0].getMimeType();
+            if (mFetechAll) { //get all list
+                if (MovieUtils.isLocalFile(uri, mime)) {
+                    String uristr = String.valueOf(uri);
+                    if (uristr.toLowerCase().startsWith("content://media")) {
+                        //from gallery, gallery3D, videoplayer
+                        long curId = Long.parseLong(uri.getPathSegments().get(3));
+                        movieList = fillUriList(null, null, curId, params[0]);
+                    } else if (uristr.toLowerCase().startsWith("file://")) {
+                        long curId = getCursorId(uri);
+                        movieList = fillUriList(null, null, curId, params[0]);
+                    }
+                }
+            } else { //get current list
+                if (MovieUtils.isLocalFile(uri, mime)) {
+                    String uristr = String.valueOf(uri);
+                    if (uristr.toLowerCase().startsWith("content://media")) {
+                        Cursor cursor = mCr.query(uri,
+                                new String[]{MediaStore.Video.Media.BUCKET_ID},
+                                null, null, null);
+                        long bucketId = -1;
+                        if (cursor != null) {
+                            if (cursor.moveToFirst()) {
+                                bucketId = cursor.getLong(0);
+                            }
+                            cursor.close();
+                        }
+                        try {
+                            long curId = Long.parseLong(uri.getPathSegments().get(3));
+                            movieList = fillUriList(MediaStore.Video.Media.BUCKET_ID + "=? ",
+                                    new String[]{String.valueOf(bucketId)}, curId, params[0]);
+                        } catch (Exception e) {
+                            Log.e(TAG, "Exception while creating movie list. " + e);
+                            return null;
+                        }
+                    } else if (uristr.toLowerCase().startsWith("file://")) {
+                        String data = Uri.decode(uri.toString());
+                        data = data.replaceAll("'", "''");
+                        String where = "_data LIKE '%" + data.replaceFirst("file:///", "") + "'";
+                        Cursor cursor = mCr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                                new String[]{"_id", MediaStore.Video.Media.BUCKET_ID},
+                                where, null, null);
+                        long bucketId = -1;
+                        long curId = -1;
+                        if (cursor != null) {
+                            if (cursor.moveToFirst()) {
+                                curId = cursor.getLong(0);
+                                bucketId = cursor.getLong(1);
+                            }
+                            cursor.close();
+                        }
+                        movieList = fillUriList(MediaStore.Video.Media.BUCKET_ID + "=? ",
+                                new String[]{String.valueOf(bucketId)}, curId, params[0]);
+                    }
+                }
+            }
+            if (LOG) {
+                Log.v(TAG, "doInBackground() done return " + movieList);
+            }
+            return movieList;
+        }
+        
+        private IMovieList fillUriList(String where, String[] whereArgs, long curId, IMovieItem current) {
+            IMovieList movieList = null;
+            Cursor cursor = null;
+            try {
+                cursor = mCr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                        new String[]{"_id", "mime_type", OpenableColumns.DISPLAY_NAME},
+                        where,
+                        whereArgs,
+                        mOrderBy);
+                boolean find = false;
+                if (cursor != null && cursor.getCount() > 0) {
+                    movieList = new MovieList();
+                    while (cursor.moveToNext()) {
+                        long id = cursor.getLong(0);
+                        if (!find && id == curId) {
+                            find = true;
+                            movieList.add(current);
+                            continue;
+                        }
+                        Uri uri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
+                        String mimeType = cursor.getString(1);
+                        String title = cursor.getString(2);
+
+                        movieList.add(new MovieItem(uri, mimeType, title));
+                    }
+                }
+            } catch (final SQLiteException e) {
+                e.printStackTrace();
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+            if (LOG) {
+                Log.v(TAG, "fillUriList() cursor=" + cursor + ", return " + movieList);
+            }
+            return movieList;
+        }
+
+        private long getCursorId(Uri uri) {
+            long curId = -1;
+            Cursor cursor = null;
+            String data = Uri.decode(uri.toString());
+            data = data.replaceAll("'", "''");
+            String where = "_data LIKE '%" + data.replaceFirst("file:///", "") + "'";
+            try {
+                cursor = mCr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                        new String[] {
+                            "_id"
+                        }, where, null, null);
+
+                if (cursor != null && cursor.moveToFirst()) {
+                    curId = cursor.getLong(0);
+                }
+            } catch (final SQLiteException e) {
+                e.printStackTrace();
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+            return curId;
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/ext/MovieUtils.java b/src/org/codeaurora/gallery3d/ext/MovieUtils.java
new file mode 100644
index 0000000..4bc70a3
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/ext/MovieUtils.java
@@ -0,0 +1,98 @@
+package org.codeaurora.gallery3d.ext;
+
+import android.net.Uri;
+import android.util.Log;
+
+import java.util.Locale;
+
+/**
+ * Util class for Movie functions. *
+ */
+public class MovieUtils {
+    private static final String TAG = "MovieUtils";
+    private static final boolean LOG = false;
+
+    private MovieUtils() {
+    }
+
+    /**
+     * Whether current video(Uri) is RTSP streaming or not.
+     *
+     * @param uri
+     * @param mimeType
+     * @return
+     */
+    public static boolean isRtspStreaming(Uri uri, String mimeType) {
+        boolean rtsp = false;
+        if (uri != null) {
+            if ("rtsp".equalsIgnoreCase(uri.getScheme())) {
+                rtsp = true;
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "isRtspStreaming(" + uri + ", " + mimeType + ") return " + rtsp);
+        }
+        return rtsp;
+    }
+
+    /**
+     * Whether current video(Uri) is HTTP streaming or not.
+     *
+     * @param uri
+     * @param mimeType
+     * @return
+     */
+    public static boolean isHttpStreaming(Uri uri, String mimeType) {
+        boolean http = false;
+        if (uri != null) {
+            if ("http".equalsIgnoreCase(uri.getScheme())) {
+                http = true;
+            } else if ("https".equalsIgnoreCase(uri.getScheme())) {
+                http = true;
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "isHttpStreaming(" + uri + ", " + mimeType + ") return " + http);
+        }
+        return http;
+    }
+
+    /**
+     * Whether current video(Uri) is live streaming or not.
+     *
+     * @param uri
+     * @param mimeType
+     * @return
+     */
+    public static boolean isSdpStreaming(Uri uri, String mimeType) {
+        boolean sdp = false;
+        if (uri != null) {
+            if ("application/sdp".equals(mimeType)) {
+                sdp = true;
+            } else if (uri.toString().toLowerCase(Locale.ENGLISH).endsWith(".sdp")) {
+                sdp = true;
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "isSdpStreaming(" + uri + ", " + mimeType + ") return " + sdp);
+        }
+        return sdp;
+    }
+
+    /**
+     * Whether current video(Uri) is local file or not.
+     *
+     * @param uri
+     * @param mimeType
+     * @return
+     */
+    public static boolean isLocalFile(Uri uri, String mimeType) {
+        boolean local = (!isSdpStreaming(uri, mimeType)
+                && !isRtspStreaming(uri, mimeType)
+                && !isHttpStreaming(uri, mimeType));
+        if (LOG) {
+            Log.v(TAG, "isLocalFile(" + uri + ", " + mimeType + ") return " + local);
+        }
+        return local;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/AbstractPermissionPreferenceActivity.java b/src/org/codeaurora/gallery3d/video/AbstractPermissionPreferenceActivity.java
new file mode 100644
index 0000000..a6be5af
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/AbstractPermissionPreferenceActivity.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+package org.codeaurora.gallery3d.video;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+import java.util.ArrayList;
+
+public abstract class AbstractPermissionPreferenceActivity extends PreferenceActivity {
+
+    public static final int PERMISSION_REQUEST_PHONE = 1;
+    private boolean permissionGranted = false;
+
+    protected abstract void onGetPermissionsSuccess();
+    protected abstract void onGetPermissionsFailure();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        requestPhonePermission();
+    }
+
+    private void requestPhonePermission() {
+        String[] permissions = {
+                Manifest.permission.READ_PHONE_STATE
+        };
+        requestPermission(permissions, PERMISSION_REQUEST_PHONE);
+    }
+
+    protected void requestPermission(String[] permissions, int requestCode) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            permissionGranted = true;
+            return;
+        }
+
+        boolean needRequest = false;
+        ArrayList<String> permissionList = new ArrayList<String>();
+        for (String permission : permissions) {
+            if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
+                permissionList.add(permission);
+                needRequest = true;
+            }
+        }
+
+        if (needRequest) {
+            int count = permissionList.size();
+            if (count > 0) {
+                String[] permissionArray = new String[count];
+                for (int i = 0; i < count; i++) {
+                    permissionArray[i] = permissionList.get(i);
+                }
+
+                requestPermissions(permissionArray, requestCode);
+            }
+        }
+        permissionGranted = !needRequest;
+    }
+
+    private boolean checkPermissionGrantResults(int[] grantResults) {
+        for (int result : grantResults) {
+            if (result != PackageManager.PERMISSION_GRANTED) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, String[] permissions,
+                                           int[] grantResults) {
+        permissionGranted = checkPermissionGrantResults(grantResults);
+        switch (requestCode) {
+            case PERMISSION_REQUEST_PHONE: {
+                if (permissionGranted) {
+                    onGetPermissionsSuccess();
+                } else {
+                    onGetPermissionsFailure();
+                }
+            }
+        }
+    }
+
+    protected boolean isPermissionGranted() {
+        return permissionGranted;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkActivity.java b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
new file mode 100644
index 0000000..75e4562
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkActivity.java
@@ -0,0 +1,244 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.AdapterContextMenuInfo;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.SimpleCursorAdapter;
+import android.widget.TextView;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.app.MovieActivity;
+
+public class BookmarkActivity extends Activity implements OnItemClickListener {
+    private static final String TAG = "BookmarkActivity";
+    private static final boolean LOG = false;
+
+    private BookmarkEnhance mBookmark;
+    private BookmarkAdapter mAdapter;
+    private Cursor mCursor;
+    private ListView mListView;
+    private TextView mEmptyView;
+
+    private static final int MENU_DELETE_ALL = 1;
+    private static final int MENU_DELETE_ONE = 2;
+    private static final int MENU_EDIT = 3;
+
+    public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+    @Override
+    protected void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.bookmark);
+
+        Bitmap logo = getIntent().getParcelableExtra(KEY_LOGO_BITMAP);
+        if (logo != null) {
+            getActionBar().setLogo(new BitmapDrawable(getResources(), logo));
+        }
+
+        mListView = (ListView) findViewById(android.R.id.list);
+        mEmptyView = (TextView) findViewById(android.R.id.empty);
+
+        mBookmark = new BookmarkEnhance(this);
+        mCursor = mBookmark.query();
+        mAdapter = new BookmarkAdapter(this, R.layout.bookmark_item, null, new String[] {},
+                new int[] {});
+        mListView.setEmptyView(mEmptyView);
+        mListView.setAdapter(mAdapter);
+        mAdapter.changeCursor(mCursor);
+
+        mListView.setOnItemClickListener(this);
+        registerForContextMenu(mListView);
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mAdapter != null) {
+            mAdapter.changeCursor(null);
+        }
+        super.onDestroy();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, MENU_DELETE_ALL, 0, R.string.delete_all)
+                .setIcon(android.R.drawable.ic_menu_delete);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        switch (item.getItemId()) {
+            case MENU_DELETE_ALL:
+                mBookmark.deleteAll();
+                return true;
+            default:
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    private class BookmarkAdapter extends SimpleCursorAdapter {
+
+        public BookmarkAdapter(final Context context, final int layout, final Cursor c,
+                final String[] from, final int[] to) {
+            super(context, layout, c, from, to);
+        }
+
+        @Override
+        public View newView(final Context context, final Cursor cursor, final ViewGroup parent) {
+            final View view = super.newView(context, cursor, parent);
+            final ViewHolder holder = new ViewHolder();
+            holder.mTitleView = (TextView) view.findViewById(R.id.title);
+            holder.mDataView = (TextView) view.findViewById(R.id.data);
+            view.setTag(holder);
+            return view;
+        }
+
+        @Override
+        public void bindView(final View view, final Context context, final Cursor cursor) {
+            final ViewHolder holder = (ViewHolder) view.getTag();
+            holder.mId = cursor.getLong(BookmarkEnhance.INDEX_ID);
+            holder.mTitle = cursor.getString(BookmarkEnhance.INDEX_TITLE);
+            holder.mData = cursor.getString(BookmarkEnhance.INDEX_DATA);
+            holder.mMimetype = cursor.getString(BookmarkEnhance.INDEX_MIME_TYPE);
+            holder.mTitleView.setText(holder.mTitle);
+            holder.mDataView.setText(holder.mData);
+        }
+
+        @Override
+        public void changeCursor(final Cursor c) {
+            super.changeCursor(c);
+        }
+
+    }
+
+    private class ViewHolder {
+        long mId;
+        String mTitle;
+        String mData;
+        String mMimetype;
+        TextView mTitleView;
+        TextView mDataView;
+    }
+
+    @Override
+    public void onItemClick(final AdapterView<?> parent, final View view, final int position,
+            final long id) {
+        final Object o = view.getTag();
+        if (o instanceof ViewHolder) {
+            final ViewHolder holder = (ViewHolder) o;
+            finish();
+            final Intent intent = new Intent(this, MovieActivity.class);
+            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            String mime = "video/*";
+            if (!(holder.mMimetype == null || "".equals(holder.mMimetype.trim()))) {
+                mime = holder.mMimetype;
+            }
+            intent.setDataAndType(Uri.parse(holder.mData), mime);
+            startActivity(intent);
+        }
+        if (LOG) {
+            Log.v(TAG, "onItemClick(" + position + ", " + id + ")");
+        }
+    }
+
+    @Override
+    public void onCreateContextMenu(final ContextMenu menu, final View v,
+            final ContextMenuInfo menuInfo) {
+        super.onCreateContextMenu(menu, v, menuInfo);
+        menu.add(0, MENU_DELETE_ONE, 0, R.string.delete);
+        menu.add(0, MENU_EDIT, 0, R.string.edit);
+    }
+
+    @Override
+    public boolean onContextItemSelected(final MenuItem item) {
+        final AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+        switch (item.getItemId()) {
+            case MENU_DELETE_ONE:
+                mBookmark.delete(info.id);
+                return true;
+            case MENU_EDIT:
+                final Object obj = info.targetView.getTag();
+                if (obj instanceof ViewHolder) {
+                    showEditDialog((ViewHolder) obj);
+                } else {
+                    Log.w(TAG, "wrong context item info " + info);
+                }
+                return true;
+            default:
+                return super.onContextItemSelected(item);
+        }
+    }
+
+    private void showEditDialog(final ViewHolder holder) {
+        if (LOG) {
+            Log.v(TAG, "showEditDialog(" + holder + ")");
+        }
+        if (holder == null) {
+            return;
+        }
+        final LayoutInflater inflater = LayoutInflater.from(this);
+        final View v = inflater.inflate(R.layout.bookmark_edit_dialog, null);
+        final EditText titleView = (EditText) v.findViewById(R.id.title);
+        final EditText dataView = (EditText) v.findViewById(R.id.data);
+        titleView.setText(holder.mTitle);
+        dataView.setText(holder.mData);
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setTitle(R.string.edit);
+        builder.setView(v);
+        builder.setIcon(R.drawable.ic_menu_display_bookmark);
+        builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
+
+            @Override
+            public void onClick(final DialogInterface dialog, final int which) {
+                mBookmark.update(holder.mId, titleView.getText().toString(),
+                        dataView.getText().toString(), 0);
+            }
+
+        });
+        builder.setNegativeButton(android.R.string.cancel, null);
+        final AlertDialog dialog = builder.create();
+        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+        dialog.setInverseBackgroundForced(true);
+        dialog.show();
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
new file mode 100644
index 0000000..a5424d6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkEnhance.java
@@ -0,0 +1,138 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.util.Log;
+
+import org.codeaurora.gallery.R;
+
+public class BookmarkEnhance {
+    private static final String TAG = "BookmarkEnhance";
+    private static final boolean LOG = false;
+
+    private static final Uri BOOKMARK_URI = Uri.parse("content://media/internal/bookmark");
+
+    public static final String COLUMN_ID = "_id";
+    public static final String COLUMN_DATA = "_data";
+    public static final String COLUMN_TITLE = "_display_name";
+    public static final String COLUMN_ADD_DATE = "date_added";
+    public static final String COLUMN_MEDIA_TYPE = "mime_type";
+    private static final String COLUMN_POSITION = "position";
+    private static final String COLUMN_MIME_TYPE = "media_type";
+
+    private static final String NULL_HOCK = COLUMN_POSITION;
+    public static final String ORDER_COLUMN = COLUMN_ADD_DATE + " ASC ";
+    private static final String VIDEO_STREAMING_MEDIA_TYPE = "streaming";
+
+    public static final int INDEX_ID = 0;
+    public static final int INDEX_DATA = 1;
+    public static final int INDEX_TITLE = 2;
+    public static final int INDEX_ADD_DATE = 3;
+    public static final int INDEX_MIME_TYPE = 4;
+    private static final int INDEX_POSITION = 5;
+    private static final int INDEX_MEDIA_TYPE = 6;
+
+    public static final String[] PROJECTION = new String[] {
+            COLUMN_ID,
+            COLUMN_DATA,
+            COLUMN_TITLE,
+            COLUMN_ADD_DATE,
+            COLUMN_MIME_TYPE,
+    };
+
+    private final Context mContext;
+    private final ContentResolver mCr;
+
+    public BookmarkEnhance(final Context context) {
+        mContext = context;
+        mCr = context.getContentResolver();
+    }
+
+    public Uri insert(final String title, final String uri, final String mimeType,
+            final long position) {
+        final ContentValues values = new ContentValues();
+        final String mytitle = (title == null ? mContext.getString(R.string.default_title) : title);
+        values.put(COLUMN_TITLE, mytitle);
+        values.put(COLUMN_DATA, uri);
+        values.put(COLUMN_POSITION, position);
+        values.put(COLUMN_ADD_DATE, System.currentTimeMillis());
+        values.put(COLUMN_MEDIA_TYPE, VIDEO_STREAMING_MEDIA_TYPE);
+        values.put(COLUMN_MIME_TYPE, mimeType);
+        final Uri insertUri = mCr.insert(BOOKMARK_URI, values);
+        if (LOG) {
+            Log.v(TAG, "insert(" + title + "," + uri + ", " + position + ") return "
+                    + insertUri);
+        }
+        return insertUri;
+    }
+
+    public int delete(final long id) {
+        final Uri uri = ContentUris.withAppendedId(BOOKMARK_URI, id);
+        final int count = mCr.delete(uri, null, null);
+        if (LOG) {
+            Log.v(TAG, "delete(" + id + ") return " + count);
+        }
+        return count;
+    }
+
+    public int deleteAll() {
+        final int count = mCr.delete(BOOKMARK_URI, COLUMN_MEDIA_TYPE + "=? ", new String[] {
+            VIDEO_STREAMING_MEDIA_TYPE
+        });
+        if (LOG) {
+            Log.v(TAG, "deleteAll() return " + count);
+        }
+        return count;
+    }
+
+    public boolean exists(final String uri) {
+        final Cursor cursor = mCr.query(BOOKMARK_URI,
+                PROJECTION,
+                COLUMN_DATA + "=? and " + COLUMN_MEDIA_TYPE + "=? ",
+                new String[] {
+                        uri, VIDEO_STREAMING_MEDIA_TYPE
+                },
+                null
+                );
+        boolean exist = false;
+        if (cursor != null) {
+            exist = cursor.moveToFirst();
+            cursor.close();
+        }
+        if (LOG) {
+            Log.v(TAG, "exists(" + uri + ") return " + exist);
+        }
+        return exist;
+    }
+
+    public Cursor query() {
+        final Cursor cursor = mCr.query(BOOKMARK_URI,
+                PROJECTION,
+                COLUMN_MEDIA_TYPE + "='" + VIDEO_STREAMING_MEDIA_TYPE + "' ",
+                null,
+                ORDER_COLUMN
+                );
+        if (LOG) {
+            Log.v(TAG, "query() return cursor=" + (cursor == null ? -1 : cursor.getCount()));
+        }
+        return cursor;
+    }
+
+    public int update(final long id, final String title, final String uri, final int position) {
+        final ContentValues values = new ContentValues();
+        values.put(COLUMN_TITLE, title);
+        values.put(COLUMN_DATA, uri);
+        values.put(COLUMN_POSITION, position);
+        final Uri updateUri = ContentUris.withAppendedId(BOOKMARK_URI, id);
+        final int count = mCr.update(updateUri, values, null, null);
+        if (LOG) {
+            Log.v(TAG, "update(" + id + ", " + title + ", " + uri + ", " + position + ")" +
+                    " return " + count);
+        }
+        return count;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/BookmarkHooker.java b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
new file mode 100644
index 0000000..867ca11
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/BookmarkHooker.java
@@ -0,0 +1,80 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.codeaurora.gallery.R;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+
+public class BookmarkHooker extends MovieHooker {
+    private static final String TAG = "BookmarkHooker";
+    private static final boolean LOG = false;
+
+    private static final String ACTION_BOOKMARK = "org.codeaurora.bookmark.VIEW";
+    private static final int MENU_BOOKMARK_ADD = 1;
+    private static final int MENU_BOOKMARK_DISPLAY = 2;
+    private MenuItem mMenuBookmarks;
+    private MenuItem mMenuBookmarkAdd;
+
+    public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        mMenuBookmarkAdd = menu.add(0, getMenuActivityId(MENU_BOOKMARK_ADD), 0,
+                R.string.bookmark_add);
+        mMenuBookmarks = menu.add(0, getMenuActivityId(MENU_BOOKMARK_DISPLAY), 0,
+                R.string.bookmark_display);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        if (MovieUtils.isLocalFile(getMovieItem().getUri(), getMovieItem().getMimeType())) {
+            if (mMenuBookmarkAdd != null) {
+                mMenuBookmarkAdd.setVisible(false);
+            }
+            if (mMenuBookmarks != null) {
+                mMenuBookmarks.setVisible(false);
+            }
+        } else {
+            if (mMenuBookmarkAdd != null) {
+                mMenuBookmarkAdd.setVisible(true);
+            }
+            if (mMenuBookmarks != null) {
+                mMenuBookmarks.setVisible(true);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch (getMenuOriginalId(item.getItemId())) {
+            case MENU_BOOKMARK_ADD:
+                getPlayer().addBookmark();
+                return true;
+            case MENU_BOOKMARK_DISPLAY:
+                gotoBookmark();
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void gotoBookmark() {
+        final Intent intent = new Intent(ACTION_BOOKMARK);
+        intent.addCategory(Intent.CATEGORY_DEFAULT);
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+                | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
+        Bitmap bitmap = getIntent().getParcelableExtra(KEY_LOGO_BITMAP);
+        if (bitmap != null) {
+            intent.putExtra(KEY_LOGO_BITMAP, bitmap);
+        }
+        getContext().startActivity(intent);
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
new file mode 100644
index 0000000..415972a
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/CodeauroraVideoView.java
@@ -0,0 +1,1126 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.AlertDialog;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnBufferingUpdateListener;
+import android.media.MediaPlayer.OnVideoSizeChangedListener;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnInfoListener;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.MediaController;
+import android.widget.MediaController.MediaPlayerControl;
+
+import com.android.gallery3d.app.MoviePlayer;
+import com.android.gallery3d.common.ApiHelper;
+import com.android.gallery3d.common.ApiHelper.Metadata;
+
+import org.codeaurora.gallery3d.video.ScreenModeManager.ScreenModeListener;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Displays a video file.  The VideoView class
+ * can load images from various sources (such as resources or content
+ * providers), takes care of computing its measurement from the video so that
+ * it can be used in any layout manager, and provides various display options
+ * such as scaling and tinting.
+ */
+public class CodeauroraVideoView extends SurfaceView implements MediaPlayerControl, ScreenModeListener{
+    private static final boolean LOG = false;
+    private String TAG = "CodeauroraVideoView";
+    // settable by the client
+    private Uri         mUri;
+    private Map<String, String> mHeaders;
+
+    // all possible internal states
+    private static final int STATE_ERROR              = -1;
+    private static final int STATE_IDLE               = 0;
+    private static final int STATE_PREPARING          = 1;
+    private static final int STATE_PREPARED           = 2;
+    private static final int STATE_PLAYING            = 3;
+    private static final int STATE_PAUSED             = 4;
+    private static final int STATE_PLAYBACK_COMPLETED = 5;
+    private static final int STATE_SUSPENDED          = 6;
+    private static final int MSG_LAYOUT_READY = 1;
+
+    // mCurrentState is a VideoView object's current state.
+    // mTargetState is the state that a method caller intends to reach.
+    // For instance, regardless the VideoView object's current state,
+    // calling pause() intends to bring the object to a target state
+    // of STATE_PAUSED.
+    private int mCurrentState = STATE_IDLE;
+    private int mTargetState  = STATE_IDLE;
+
+    // All the stuff we need for playing and showing a video
+    private SurfaceHolder mSurfaceHolder = null;
+    private MediaPlayer mMediaPlayer = null;
+    private int         mAudioSession;
+    private int         mVideoWidth;
+    private int         mVideoHeight;
+    private int         mSurfaceWidth;
+    private int         mSurfaceHeight;
+    private int         mDuration;
+    private MediaController mMediaController;
+    private OnCompletionListener mOnCompletionListener;
+    private MediaPlayer.OnPreparedListener mOnPreparedListener;
+    private MediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener;
+    private MediaPlayer.OnVideoSizeChangedListener mVideoSizeListener;
+    private MediaPlayer.OnPreparedListener mPreparedListener;
+    private ScreenModeManager mScreenManager;
+    private MoviePlayer.TimerProgress mTimerController;
+    private int         mCurrentBufferPercentage;
+    private OnErrorListener mOnErrorListener;
+    private OnInfoListener  mOnInfoListener;
+    private int         mSeekWhenPrepared;  // recording the seek position while preparing
+    private boolean     mCanPause;
+    private boolean     mCanSeekBack;
+    private boolean     mCanSeekForward;
+    private boolean     mCanSeek;
+    private boolean     mHasGotPreparedCallBack = false;
+    private boolean mNeedWaitLayout = false;
+    private boolean mHasGotMetaData = false;
+    private boolean mOnResumed;
+    private boolean mIsShowDialog = false;
+    private boolean mErrorDialogShowing = false;
+    private KeyguardManager mKeyguardManager;
+
+    private final Handler mHandler = new Handler() {
+        public void handleMessage(final Message msg) {
+            if (LOG) {
+                Log.v(TAG, "handleMessage() to do prepare. msg=" + msg);
+            }
+            switch (msg.what) {
+                case MSG_LAYOUT_READY:
+                    if (mMediaPlayer == null || mUri == null) {
+                        Log.w(TAG, "Cannot prepare play! mMediaPlayer=" + mMediaPlayer
+                                + ", mUri=" + mUri);
+                        return;
+                    }
+                    doPreparedIfReady(mMediaPlayer);
+                    break;
+                default:
+                    Log.w(TAG, "Unhandled message " + msg);
+                    break;
+            }
+        }
+    };
+
+    public CodeauroraVideoView(Context context) {
+        super(context);
+        initVideoView();
+        initialize();
+    }
+
+    public CodeauroraVideoView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+        initVideoView();
+        initialize();
+    }
+
+    public CodeauroraVideoView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        initVideoView();
+        initialize();
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int width = 0;
+        int height = 0;
+        int screenMode = ScreenModeManager.SCREENMODE_BIGSCREEN;
+        if (mScreenManager != null) {
+            screenMode = mScreenManager.getScreenMode();
+        }
+        switch (screenMode) {
+            case ScreenModeManager.SCREENMODE_BIGSCREEN:
+                width = getDefaultSize(mVideoWidth, widthMeasureSpec);
+                height = getDefaultSize(mVideoHeight, heightMeasureSpec);
+                if (mVideoWidth > 0 && mVideoHeight > 0) {
+                    if (mVideoWidth * height > width * mVideoHeight) {
+                        height = width * mVideoHeight / mVideoWidth;
+                    } else if (mVideoWidth * height < width * mVideoHeight) {
+                        width = height * mVideoWidth / mVideoHeight;
+                    }
+                }
+                break;
+            case ScreenModeManager.SCREENMODE_FULLSCREEN:
+                width = getDefaultSize(mVideoWidth, widthMeasureSpec);
+                height = getDefaultSize(mVideoHeight, heightMeasureSpec);
+                break;
+            case ScreenModeManager.SCREENMODE_CROPSCREEN:
+                width = getDefaultSize(mVideoWidth, widthMeasureSpec);
+                height = getDefaultSize(mVideoHeight, heightMeasureSpec);
+                if (mVideoWidth > 0 && mVideoHeight > 0) {
+                    if (mVideoWidth * height > width * mVideoHeight) {
+                        width = height * mVideoWidth / mVideoHeight;
+                    } else if (mVideoWidth * height < width * mVideoHeight) {
+                        height = width * mVideoHeight / mVideoWidth;
+                    }
+                }
+                break;
+            default:
+                Log.w(TAG, "wrong screen mode : " + screenMode);
+                break;
+        }
+        if (LOG) {
+            Log.v(TAG, "onMeasure() set size: " + width + 'x' + height);
+            Log.v(TAG, "onMeasure() video size: " + mVideoWidth + 'x' + mVideoHeight);
+            Log.v(TAG, "onMeasure() mNeedWaitLayout=" + mNeedWaitLayout);
+        }
+        setMeasuredDimension(width, height);
+        if (mNeedWaitLayout || mCurrentState == STATE_PREPARING) { // when OnMeasure ok, start video.
+            mNeedWaitLayout = false;
+            mHandler.sendEmptyMessage(MSG_LAYOUT_READY);
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CodeauroraVideoView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CodeauroraVideoView.class.getName());
+    }
+
+    public int resolveAdjustedSize(int desiredSize, int measureSpec) {
+        return getDefaultSize(desiredSize, measureSpec);
+    }
+
+    private void initVideoView() {
+        mVideoWidth = 0;
+        mVideoHeight = 0;
+        getHolder().addCallback(mSHCallback);
+        getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        requestFocus();
+        mCurrentState = STATE_IDLE;
+        mTargetState  = STATE_IDLE;
+    }
+
+    private void initialize() {
+        mPreparedListener = new MediaPlayer.OnPreparedListener() {
+            public void onPrepared(final MediaPlayer mp) {
+                if (LOG) {
+                    Log.v(TAG, "mPreparedListener.onPrepared(" + mp + ")");
+                }
+                //Here we can get meta data from mediaplayer.
+                // Get the capabilities of the player for this stream
+                final Metadata data = ApiHelper.MediaPlayer.getMetadata(mp,
+                        ApiHelper.MediaPlayer.METADATA_ALL,
+                        ApiHelper.MediaPlayer.BYPASS_METADATA_FILTER);
+                if (data != null) {
+                    mCanPause = !data.has(Metadata.PAUSE_AVAILABLE)
+                            || data.getBoolean(Metadata.PAUSE_AVAILABLE);
+                    mCanSeekBack = !data.has(Metadata.SEEK_BACKWARD_AVAILABLE)
+                            || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE);
+                    mCanSeekForward = !data.has(Metadata.SEEK_FORWARD_AVAILABLE)
+                            || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE);
+                    mCanSeek = !data.has(Metadata.SEEK_AVAILABLE)
+                            || data.getBoolean(Metadata.SEEK_AVAILABLE);
+                } else {
+                    mCanPause = true;
+                    mCanSeekBack = true;
+                    mCanSeekForward = true;
+                    mCanSeek = true;
+                    Log.w(TAG, "Metadata is null!");
+                }
+                if (LOG) {
+                    Log.v(TAG, "mPreparedListener.onPrepared() mCanPause=" + mCanPause);
+                }
+                mHasGotPreparedCallBack = true;
+                doPreparedIfReady(mMediaPlayer);
+            }
+        };
+
+        mErrorListener = new MediaPlayer.OnErrorListener() {
+            public boolean onError(final MediaPlayer mp, final int frameworkErr, final int implErr) {
+                Log.d(TAG, "Error: " + frameworkErr + "," + implErr);
+                //record error position and duration
+                //here disturb the original logic
+                mSeekWhenPrepared = getCurrentPosition();
+                if (LOG) {
+                    Log.v(TAG, "onError() mSeekWhenPrepared=" + mSeekWhenPrepared + ", mDuration=" + mDuration);
+                }
+                //for old version Streaming server, getduration is not valid.
+                mDuration = Math.abs(mDuration);
+                mCurrentState = STATE_ERROR;
+                mTargetState = STATE_ERROR;
+                if (mMediaController != null) {
+                    mMediaController.hide();
+                }
+
+                /* If an error handler has been supplied, use it and finish. */
+                if (mOnErrorListener != null) {
+                    if (mOnErrorListener.onError(mMediaPlayer, frameworkErr, implErr)) {
+                        return true;
+                    }
+                }
+
+                mMediaPlayer.reset();
+                /* Otherwise, pop up an error dialog so the user knows that
+                 * something bad has happened. Only try and pop up the dialog
+                 * if we're attached to a window. When we're going away and no
+                 * longer have a window, don't bother showing the user an error.
+                 */
+                if (getWindowToken() != null && mErrorDialogShowing == false) {
+                    final Resources r = getContext().getResources();
+                    int messageId;
+
+                    if (frameworkErr == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) {
+                        messageId = android.R.string.VideoView_error_text_invalid_progressive_playback;
+                    } else {
+                        messageId = android.R.string.VideoView_error_text_unknown;
+                    }
+                     new AlertDialog.Builder(getContext())
+                        .setMessage(messageId)
+                        .setPositiveButton(android.R.string.VideoView_error_button,
+                                new DialogInterface.OnClickListener() {
+                                    public void onClick(DialogInterface dialog, int whichButton) {
+                                        /* If we get here, there is no onError listener, so
+                                         * at least inform them that the video is over.
+                                         */
+                                        mErrorDialogShowing = false;
+                                        if (mOnCompletionListener != null) {
+                                            mOnCompletionListener.onCompletion(mMediaPlayer);
+                                        }
+                                        release(true);
+                                    }
+                                })
+                        .setCancelable(false)
+                        .show();
+                     mErrorDialogShowing = true;
+                }
+                return true;
+            }
+        };
+
+        mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
+            public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
+                mCurrentBufferPercentage = percent;
+                if (mOnBufferingUpdateListener != null) {
+                    mOnBufferingUpdateListener.onBufferingUpdate(mp, percent);
+                }
+                if (LOG) {
+                    Log.v(TAG, "onBufferingUpdate() Buffering percent: " + percent);
+                    Log.v(TAG, "onBufferingUpdate() mTargetState=" + mTargetState);
+                    Log.v(TAG, "onBufferingUpdate() mCurrentState=" + mCurrentState);
+                }
+            }
+        };
+
+        mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
+            public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
+                mVideoWidth = mp.getVideoWidth();
+                mVideoHeight = mp.getVideoHeight();
+                if (LOG) {
+                    Log.v(TAG, "OnVideoSizeChagned(" + width + "," + height + ")");
+                    Log.v(TAG, "OnVideoSizeChagned(" + mVideoWidth + "," + mVideoHeight + ")");
+                    Log.v(TAG, "OnVideoSizeChagned() mCurrentState=" + mCurrentState);
+                }
+                if (mVideoWidth != 0 && mVideoHeight != 0) {
+                    getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+                    if (mCurrentState == STATE_PREPARING) {
+                        mNeedWaitLayout = true;
+                    }
+                }
+                if (mVideoSizeListener != null) {
+                    mVideoSizeListener.onVideoSizeChanged(mp, width, height);
+                }
+                CodeauroraVideoView.this.requestLayout();
+            }
+        };
+
+        getHolder().removeCallback(mSHCallback);
+        mSHCallback = new SurfaceHolder.Callback() {
+            public void surfaceChanged(final SurfaceHolder holder, final int format,
+                    final int w, final int h) {
+                if (LOG) {
+                    Log.v(TAG, "surfaceChanged(" + holder + ", " + format
+                            + ", " + w + ", " + h + ")");
+                    Log.v(TAG, "surfaceChanged() mMediaPlayer=" + mMediaPlayer
+                            + ", mTargetState=" + mTargetState
+                            + ", mVideoWidth=" + mVideoWidth
+                            + ", mVideoHeight=" + mVideoHeight);
+                }
+                mSurfaceWidth = w;
+                mSurfaceHeight = h;
+                final boolean isValidState =  (mTargetState == STATE_PLAYING);
+                final boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
+                if (mMediaPlayer != null && isValidState && hasValidSize) {
+                    if (mSeekWhenPrepared != 0) {
+                        seekTo(mSeekWhenPrepared);
+                    }
+                    Log.v(TAG, "surfaceChanged() start()");
+                    start();
+                }
+            }
+
+            public void surfaceCreated(final SurfaceHolder holder) {
+                if (LOG) {
+                    Log.v(TAG, "surfaceCreated(" + holder + ")");
+                }
+                /*
+                if (mCurrentState == STATE_SUSPENDED) {
+                    mSurfaceHolder = holder;
+                    mMediaPlayer.setDisplay(mSurfaceHolder);
+                    if (mMediaPlayer.resume()) {
+                        mCurrentState = STATE_PREPARED;
+                        if (mSeekWhenPrepared != 0) {
+                            seekTo(mSeekWhenPrepared);
+                        }
+                        if (mTargetState == STATE_PLAYING) {
+                            start();
+                        }
+                        return;
+                    } else {
+                        release(false);
+                    }
+                }
+                */
+                mSurfaceHolder = holder;
+                openVideo();
+            }
+
+            public void surfaceDestroyed(final SurfaceHolder holder) {
+                // after we return from this we can't use the surface any more
+                if (LOG) {
+                    Log.v(TAG, "surfaceDestroyed(" + holder + ")");
+                }
+                mSurfaceHolder = null;
+                if (mMediaController != null) {
+                    mMediaController.hide();
+                }
+                if (isHTTPStreaming(mUri) && mCurrentState == STATE_SUSPENDED) {
+                    // Don't call release() while run suspend operation
+                    return;
+                }
+                release(mTargetState == STATE_ERROR || mCurrentState == STATE_ERROR);
+            }
+        };
+        getHolder().addCallback(mSHCallback);
+    }
+
+    public void setVideoPath(String path) {
+        setVideoURI(Uri.parse(path));
+    }
+
+    public void setVideoURI(Uri uri) {
+        setVideoURI(uri, null);
+    }
+
+    /**
+     * @hide
+     */
+    public void setVideoURI(Uri uri, Map<String, String> headers) {
+        Log.d(TAG,"setVideoURI uri = " + uri);
+        mDuration = -1;
+        setResumed(true);
+        mUri = uri;
+        mHeaders = headers;
+        mSeekWhenPrepared = 0;
+        openVideo();
+        requestLayout();
+        invalidate();
+    }
+
+    public void stopPlayback() {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.stop();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            mCurrentState = STATE_IDLE;
+            mTargetState  = STATE_IDLE;
+        }
+    }
+
+    private void openVideo() {
+        clearVideoInfo();
+        if (mUri == null || mSurfaceHolder == null || mTargetState == STATE_ERROR) {
+            // not ready for playback just yet, will try again later
+            return;
+        }
+
+        // we shouldn't clear the target state, because somebody might have
+        // called start() previously
+        release(false);
+        if ("".equalsIgnoreCase(String.valueOf(mUri))) {
+            Log.w(TAG, "Unable to open content: " + mUri);
+            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+            return;
+        }
+
+        try {
+            mMediaPlayer = new MediaPlayer();
+            if (mAudioSession != 0) {
+                mMediaPlayer.setAudioSessionId(mAudioSession);
+            } else {
+                mAudioSession = mMediaPlayer.getAudioSessionId();
+            }
+            mMediaPlayer.setOnPreparedListener(mPreparedListener);
+            mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
+            mMediaPlayer.setOnCompletionListener(mCompletionListener);
+            mMediaPlayer.setOnErrorListener(mErrorListener);
+            mMediaPlayer.setOnInfoListener(mOnInfoListener);
+            mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
+            mCurrentBufferPercentage = 0;
+            mMediaPlayer.setDataSource(getContext(), mUri, mHeaders);
+            mMediaPlayer.setDisplay(mSurfaceHolder);
+            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mMediaPlayer.setScreenOnWhilePlaying(true);
+            mMediaPlayer.prepareAsync();
+            // we don't set the target state here either, but preserve the
+            // target state that was there before.
+            mCurrentState = STATE_PREPARING;
+            attachMediaController();
+        } catch (IOException ex) {
+            Log.w(TAG, "Unable to open content: " + mUri, ex);
+            mCurrentState = STATE_ERROR;
+            mTargetState = STATE_ERROR;
+            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+            return;
+        } catch (IllegalArgumentException ex) {
+            Log.w(TAG, "Unable to open content: " + mUri, ex);
+            mCurrentState = STATE_ERROR;
+            mTargetState = STATE_ERROR;
+            mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+            return;
+        }
+    }
+
+    public void setMediaController(MediaController controller) {
+        if (mMediaController != null) {
+            mMediaController.hide();
+        }
+        mMediaController = controller;
+        attachMediaController();
+    }
+
+    private void attachMediaController() {
+        if (mMediaPlayer != null && mMediaController != null) {
+            mMediaController.setMediaPlayer(this);
+            View anchorView = this.getParent() instanceof View ?
+                    (View)this.getParent() : this;
+            mMediaController.setAnchorView(anchorView);
+            mMediaController.setEnabled(isInPlaybackState());
+        }
+    }
+
+    private boolean isHTTPStreaming(Uri mUri) {
+        if (mUri != null){
+            String scheme = mUri.toString();
+            if (scheme.startsWith("http://") || scheme.startsWith("https://")) {
+                if (scheme.endsWith(".m3u8") || scheme.endsWith(".m3u")
+                    || scheme.contains("m3u8") || scheme.endsWith(".mpd")) {
+                    // HLS or DASH streaming source
+                    return false;
+                }
+                // HTTP streaming
+                return true;
+            }
+        }
+        return false;
+    }
+
+    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener =
+        new MediaPlayer.OnVideoSizeChangedListener() {
+            public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
+                mVideoWidth = mp.getVideoWidth();
+                mVideoHeight = mp.getVideoHeight();
+                if (mVideoWidth != 0 && mVideoHeight != 0) {
+                    getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+                    requestLayout();
+                }
+            }
+    };
+
+    private MediaPlayer.OnCompletionListener mCompletionListener =
+        new MediaPlayer.OnCompletionListener() {
+        public void onCompletion(MediaPlayer mp) {
+            mCurrentState = STATE_PLAYBACK_COMPLETED;
+            mTargetState = STATE_PLAYBACK_COMPLETED;
+            if (mMediaController != null) {
+                mMediaController.hide();
+            }
+            if (mOnCompletionListener != null) {
+                printMetrics("OnCompletion: ");
+                mOnCompletionListener.onCompletion(mMediaPlayer);
+            }
+        }
+    };
+
+    private MediaPlayer.OnErrorListener mErrorListener;
+
+    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
+        new MediaPlayer.OnBufferingUpdateListener() {
+        public void onBufferingUpdate(MediaPlayer mp, int percent) {
+            mCurrentBufferPercentage = percent;
+        }
+    };
+
+    /**
+     * Register a callback to be invoked when the media file
+     * is loaded and ready to go.
+     *
+     * @param l The callback that will be run
+     */
+    public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
+        mOnPreparedListener = l;
+    }
+
+    /**
+     * Register a callback to be invoked when the end of a media file
+     * has been reached during playback.
+     *
+     * @param l The callback that will be run
+     */
+    public void setOnCompletionListener(OnCompletionListener l) {
+        mOnCompletionListener = l;
+    }
+
+    /**
+     * Register a callback to be invoked when an error occurs
+     * during playback or setup.  If no listener is specified,
+     * or if the listener returned false, VideoView will inform
+     * the user of any errors.
+     *
+     * @param l The callback that will be run
+     */
+    public void setOnErrorListener(OnErrorListener l) {
+        mOnErrorListener = l;
+    }
+
+    /**
+     * Register a callback to be invoked when an informational event
+     * occurs during playback or setup.
+     *
+     * @param l The callback that will be run
+     */
+    public void setOnInfoListener(OnInfoListener l) {
+        mOnInfoListener = l;
+    }
+
+    /**
+     * Register a callback to start Timer for time progress bar
+     * occurs during this.start()
+     *
+     * @param c The callback that will be run
+     */
+    public void setTimerProgress(MoviePlayer.TimerProgress c) {
+        mTimerController = c;
+    }
+
+    SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() {
+        public void surfaceChanged(SurfaceHolder holder, int format,
+                                    int w, int h) {
+            mSurfaceWidth = w;
+            mSurfaceHeight = h;
+            boolean isValidState =  (mTargetState == STATE_PLAYING);
+            boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h);
+            if (mMediaPlayer != null && isValidState && hasValidSize) {
+                if (mSeekWhenPrepared != 0) {
+                    seekTo(mSeekWhenPrepared);
+                }
+                start();
+            }
+        }
+
+        public void surfaceCreated(SurfaceHolder holder) {
+            if (LOG) {
+                Log.v(TAG, "surfaceCreated(" + holder + ")");
+            }
+            /*
+            if (mCurrentState == STATE_SUSPENDED) {
+                mSurfaceHolder = holder;
+                mMediaPlayer.setDisplay(mSurfaceHolder);
+                if (mMediaPlayer.resume()) {
+                    mCurrentState = STATE_PREPARED;
+                    if (mSeekWhenPrepared != 0) {
+                        seekTo(mSeekWhenPrepared);
+                    }
+                    if (mTargetState == STATE_PLAYING) {
+                        start();
+                    }
+                    return;
+                } else {
+                    release(false);
+                }
+            }
+            */
+            mSurfaceHolder = holder;
+            openVideo();
+        }
+
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            // after we return from this we can't use the surface any more
+            mSurfaceHolder = null;
+            if (mMediaController != null) mMediaController.hide();
+            if (isHTTPStreaming(mUri) && mCurrentState == STATE_SUSPENDED) {
+                // Don't call release() while run suspend operation
+                return;
+            }
+            release(true);
+        }
+    };
+
+    /*
+     * release the media player in any state
+     */
+    private void release(boolean cleartargetstate) {
+        if (mMediaPlayer != null) {
+            mMediaPlayer.reset();
+            mMediaPlayer.release();
+            mMediaPlayer = null;
+            mCurrentState = STATE_IDLE;
+            if (cleartargetstate) {
+                mTargetState  = STATE_IDLE;
+            }
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (isInPlaybackState() && mMediaController != null) {
+            toggleMediaControlsVisiblity();
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent ev) {
+        if (isInPlaybackState() && mMediaController != null) {
+            toggleMediaControlsVisiblity();
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        final boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
+                keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
+                keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
+                keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
+                keyCode != KeyEvent.KEYCODE_MENU &&
+                keyCode != KeyEvent.KEYCODE_CALL &&
+                keyCode != KeyEvent.KEYCODE_ENDCALL &&
+                keyCode != KeyEvent.KEYCODE_CAMERA;
+        if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
+            if (event.getRepeatCount() == 0 && (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)) {
+                if (mMediaPlayer.isPlaying()) {
+                    pause();
+                    mMediaController.show();
+                } else {
+                    start();
+                    mMediaController.hide();
+                }
+                return true;
+            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
+                if (!mMediaPlayer.isPlaying()) {
+                    start();
+                    mMediaController.hide();
+                }
+                return true;
+            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
+                    || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
+                if (mMediaPlayer.isPlaying()) {
+                    pause();
+                    mMediaController.show();
+                }
+                return true;
+            } else if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_NEXT ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_REWIND ||
+                    keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
+                    keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
+                // consume media action, so if video view if front,
+                // other media player will not play any sounds.
+                return true;
+            } else {
+                toggleMediaControlsVisiblity();
+            }
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    private void toggleMediaControlsVisiblity() {
+        if (mMediaController.isShowing()) {
+            mMediaController.hide();
+        } else {
+            mMediaController.show();
+        }
+    }
+
+    public void setDialogShowState(boolean isDialogShow) {
+        mIsShowDialog = isDialogShow;
+    }
+
+    @Override
+    public void start() {
+        if (mIsShowDialog) return;
+        if (isInPlaybackState()) {
+            mMediaPlayer.start();
+            mTimerController.startTimer();
+            mCurrentState = STATE_PLAYING;
+        }
+        mTargetState = STATE_PLAYING;
+    }
+
+    @Override
+    public void pause() {
+        if (isInPlaybackState()) {
+            if (mMediaPlayer.isPlaying()) {
+                mMediaPlayer.pause();
+                mCurrentState = STATE_PAUSED;
+            }
+        }
+        mTargetState = STATE_PAUSED;
+    }
+
+    public void suspend() {
+        // HTTP streaming will call mMediaPlayer->suspend(), others will call release()
+        /*
+        if (isHTTPStreaming(mUri) && mCurrentState != STATE_PREPARING) {
+            if (mMediaPlayer != null) {
+                if (mMediaPlayer.suspend()) {
+                    mTargetState = mCurrentState;
+                    mCurrentState = STATE_SUSPENDED;
+                    return;
+                }
+            }
+        }
+        */
+        printMetrics("Suspend: ");
+        release(false);
+    }
+
+    private void printMetrics(String preLog) {
+       if (mMediaPlayer == null)return;
+       PersistableBundle metrics = mMediaPlayer.getMetrics();
+       if (metrics != null) {
+           long frames = metrics.getLong(MediaPlayer.MetricsConstants.FRAMES);
+           long dropFrames = metrics.getLong(MediaPlayer.MetricsConstants.FRAMES_DROPPED);
+           float percentageDropped = (frames == 0) ? 0 : (100*(float)dropFrames/frames);
+           String log = preLog + "\n"
+                   + "CODEC_AUDIO: " + metrics.getString(MediaPlayer.MetricsConstants.CODEC_AUDIO) + "\n"
+                   + "DURATION: " + metrics.getLong(MediaPlayer.MetricsConstants.DURATION) + "\n"
+                   + "CODEC_VIDEO: " + metrics.getString(MediaPlayer.MetricsConstants.CODEC_VIDEO) + "\n"
+                   + "MIME_TYPE_VIDEO: " + metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_VIDEO) + "\n"
+                   + "MIME_TYPE_AUDIO: " + metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_AUDIO) + "\n"
+                   + "FRAMES: " + frames + " DROP: " + dropFrames + " DropPecentage: " + percentageDropped + "%" + "\n"
+                   + "RESOLUTION: " + metrics.getInt(MediaPlayer.MetricsConstants.WIDTH) + "x" +
+                   metrics.getInt(MediaPlayer.MetricsConstants.HEIGHT);
+           Log.d(TAG, log);
+       }
+    }
+
+    public void resume() {
+        // HTTP streaming (with suspended status) will call mMediaPlayer->resume(),
+        // others will call openVideo()
+        /*
+        if (mCurrentState == STATE_SUSPENDED) {
+            if (mSurfaceHolder != null) {
+                // The surface hasn't been destroyed
+                if (mMediaPlayer.resume()) {
+                    mCurrentState = STATE_PREPARED;
+                    if (mSeekWhenPrepared !=0) {
+                        seekTo(mSeekWhenPrepared);
+                    }
+                    if (mTargetState == STATE_PLAYING) {
+                        start();
+                    }
+                    return;
+                } else {
+                     // resume failed, so call release() before openVideo()
+                     release(false);
+                }
+            } else {
+                // The surface has been destroyed, resume operation will be done
+                // after surface created
+                return;
+            }
+        }
+        */
+        openVideo();
+    }
+
+    @Override
+    public int getDuration() {
+        final boolean inPlaybackState = isInPlaybackState();
+        if (LOG) {
+            Log.v(TAG, "getDuration() mDuration=" + mDuration + ", inPlaybackState="
+                    + inPlaybackState);
+        }
+        if (inPlaybackState) {
+            if (mDuration > 0) {
+                return mDuration;
+            }
+            // in case the duration is zero or smaller than zero for streaming
+            // video
+            int tempDuration = mMediaPlayer.getDuration();
+            if (tempDuration <= 0) {
+                return mDuration;
+            } else {
+                mDuration = tempDuration;
+            }
+
+            return mDuration;
+        }
+        return mDuration;
+    }
+
+    @Override
+    public int getCurrentPosition() {
+        int position = 0;
+        if (mSeekWhenPrepared > 0) {
+            // if connecting error before seek,
+            // we should remember this position for retry
+            position = mSeekWhenPrepared;
+            // /M: if player not started, getCurrentPosition() will lead to NE.
+        } else if (isInPlaybackState()) {
+            position = mMediaPlayer.getCurrentPosition();
+        }
+        if (LOG) {
+            Log.v(TAG, "getCurrentPosition() return " + position
+                    + ", mSeekWhenPrepared=" + mSeekWhenPrepared);
+        }
+        return position;
+    }
+
+    @Override
+    public void seekTo(int msec) {
+        if (isInPlaybackState()) {
+            mMediaPlayer.seekTo(msec);
+            mSeekWhenPrepared = 0;
+        } else {
+            mSeekWhenPrepared = msec;
+        }
+    }
+
+    @Override
+    public boolean isPlaying() {
+        return isInPlaybackState() && mMediaPlayer.isPlaying();
+    }
+
+    @Override
+    public int getBufferPercentage() {
+        if (mMediaPlayer != null) {
+            return mCurrentBufferPercentage;
+        }
+        return 0;
+    }
+
+    private boolean isInPlaybackState() {
+        return (mMediaPlayer != null &&
+                mCurrentState != STATE_ERROR &&
+                mCurrentState != STATE_IDLE &&
+                mCurrentState != STATE_PREPARING &&
+                mCurrentState != STATE_SUSPENDED);
+    }
+
+    @Override
+    public boolean canPause() {
+        return mCanPause;
+    }
+
+    @Override
+    public boolean canSeekBackward() {
+        return mCanSeekBack;
+    }
+
+    @Override
+    public boolean canSeekForward() {
+        return mCanSeekForward;
+    }
+
+    public boolean canSeek() {
+        return mCanSeek;
+    }
+
+    @Override
+    public int getAudioSessionId() {
+        if (mAudioSession == 0) {
+            MediaPlayer foo = new MediaPlayer();
+            mAudioSession = foo.getAudioSessionId();
+            foo.release();
+        }
+        return mAudioSession;
+    }
+
+    // for duration displayed
+    public void setDuration(final int duration) {
+        if (LOG) {
+            Log.v(TAG, "setDuration(" + duration + ")");
+        }
+        mDuration = (duration > 0 ? -duration : duration);
+    }
+
+    public void setVideoURI(final Uri uri, final Map<String, String> headers,
+            final boolean hasGotMetaData) {
+        if (LOG) {
+            Log.v(TAG, "setVideoURI(" + uri + ", " + headers + ")");
+        }
+        // clear the flags
+        mHasGotMetaData = hasGotMetaData;
+        setVideoURI(uri, headers);
+    }
+
+    private boolean isKeyguardLocked() {
+        if (mKeyguardManager == null) {
+            mKeyguardManager =
+                    (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
+        }
+        // isKeyguardSecure excludes the slide lock case.
+        boolean locked = (mKeyguardManager != null)
+                && mKeyguardManager.inKeyguardRestrictedInputMode();
+        if (LOG) {
+            Log.v(TAG, "isKeyguardLocked() locked=" + locked + ", mKeyguardManager="
+                    + mKeyguardManager);
+        }
+        return locked;
+    }
+
+    private void doPreparedIfReady(final MediaPlayer mp) {
+        if (LOG) {
+            Log.v(TAG, "doPreparedIfReady() mHasGotPreparedCallBack=" + mHasGotPreparedCallBack
+                    + ", mHasGotMetaData=" + mHasGotMetaData + ", mNeedWaitLayout="
+                    + mNeedWaitLayout
+                    + ", mCurrentState=" + mCurrentState);
+        }
+        if (mHasGotPreparedCallBack && mHasGotMetaData && !mNeedWaitLayout && !isKeyguardLocked()) {
+            doPrepared(mp);
+        }
+    }
+
+    private void doPrepared(final MediaPlayer mp) {
+        if (LOG) {
+            Log.v(TAG, "doPrepared(" + mp + ") start");
+        }
+        mCurrentState = STATE_PREPARED;
+        if (mOnPreparedListener != null) {
+            mOnPreparedListener.onPrepared(mMediaPlayer);
+        }
+        mVideoWidth = mp.getVideoWidth();
+        mVideoHeight = mp.getVideoHeight();
+
+        // mSeekWhenPrepared may be changed after seekTo()
+        final int seekToPosition = mSeekWhenPrepared;
+        if (seekToPosition != 0) {
+            seekTo(seekToPosition);
+        }
+        if (mVideoWidth != 0 && mVideoHeight != 0) {
+            getHolder().setFixedSize(mVideoWidth, mVideoHeight);
+        }
+
+        if (mTargetState == STATE_PLAYING) {
+            start();
+        }
+        if (LOG) {
+            Log.v(TAG, "doPrepared() end video size: " + mVideoWidth + "," + mVideoHeight
+                    + ", mTargetState=" + mTargetState + ", mCurrentState=" + mCurrentState);
+        }
+    }
+
+    /**
+     * surfaceCreate will invoke openVideo after the activity stoped. Here set
+     * this flag to avoid openVideo after the activity stoped.
+     *
+     * @param resume
+     */
+    public void setResumed(final boolean resume) {
+        if (LOG) {
+            Log.v(TAG, "setResumed(" + resume + ") mUri=" + mUri + ", mOnResumed=" + mOnResumed);
+        }
+        mOnResumed = resume;
+    }
+
+    private void clearVideoInfo() {
+        if (LOG) {
+            Log.v(TAG, "clearVideoInfo()");
+        }
+        mHasGotPreparedCallBack = false;
+        mNeedWaitLayout = false;
+    }
+
+    public void clearSeek() {
+        if (LOG) {
+            Log.v(TAG, "clearSeek() mSeekWhenPrepared=" + mSeekWhenPrepared);
+        }
+        mSeekWhenPrepared = 0;
+    }
+
+    public void clearDuration() {
+        if (LOG) {
+            Log.v(TAG, "clearDuration() mDuration=" + mDuration);
+        }
+        mDuration = -1;
+    }
+
+    public boolean isTargetPlaying() {
+        if (LOG) {
+            Log.v(TAG, "isTargetPlaying() mTargetState=" + mTargetState);
+        }
+        return mTargetState == STATE_PLAYING;
+    }
+
+    public void setScreenModeManager(final ScreenModeManager manager) {
+        mScreenManager = manager;
+        if (mScreenManager != null) {
+            mScreenManager.addListener(this);
+        }
+        if (LOG) {
+            Log.v(TAG, "setScreenModeManager(" + manager + ")");
+        }
+    }
+
+    @Override
+    public void onScreenModeChanged(final int newMode) {
+        this.requestLayout();
+    }
+
+    public void setOnVideoSizeChangedListener(final OnVideoSizeChangedListener l) {
+        mVideoSizeListener = l;
+        if (LOG) {
+            Log.i(TAG, "setOnVideoSizeChangedListener(" + l + ")");
+        }
+    }
+
+    public void setOnBufferingUpdateListener(final OnBufferingUpdateListener l) {
+        mOnBufferingUpdateListener = l;
+        if (LOG) {
+            Log.v(TAG, "setOnBufferingUpdateListener(" + l + ")");
+        }
+    }
+
+    public MediaPlayer getMediaPlayer() {
+        return mMediaPlayer;
+    }
+
+    public Uri getUri() {
+        return mUri;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/DmReceiver.java b/src/org/codeaurora/gallery3d/video/DmReceiver.java
new file mode 100644
index 0000000..616ce33
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/DmReceiver.java
@@ -0,0 +1,65 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.preference.PreferenceManager;
+import android.provider.Settings.System;
+import android.util.Log;
+
+public class DmReceiver extends BroadcastReceiver {
+    private static final String TAG = "DmReceiver";
+    public static final String WRITE_SETTING_ACTION = "streaming.action.WRITE_SETTINGS";
+    public static final String BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
+
+    private SharedPreferences mPref;
+    static final int STREAMING_CONNPROFILE_IO_HANDLER_TYPE = 1;
+    static final int STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE = 3;
+    static final int STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE = 4;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (mPref == null) {
+            mPref = PreferenceManager.getDefaultSharedPreferences(context);
+        }
+        if (BOOT_COMPLETED.equals(intent.getAction())) {
+            String rtpMaxport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MAXPORT, "65535");
+            String rtpMinport = mPref.getString(SettingsActivity.PREFERENCE_RTP_MINPORT, "8192");
+            String apn = mPref.getString(SettingsActivity.PREFERENCE_APN, "CMWAP");
+            System.putString(context.getContentResolver(),
+                    "streaming_max_udp_port", rtpMaxport);
+            System.putString(context.getContentResolver(),
+                    "streaming_min_udp_port", rtpMinport);
+            System.putString(context.getContentResolver(), "apn", apn);
+        } else if (WRITE_SETTING_ACTION.equals(intent.getAction())) {
+            int valueType = intent.getIntExtra("type", 0);
+            String value = intent.getStringExtra("value");
+            if (valueType == STREAMING_MAX_UDP_PORT_IO_HANDLER_TYPE) {
+                mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MAXPORT,
+                        value).commit();
+                System.putString(context.getContentResolver(),
+                        "streaming_max_udp_port", value);
+            } else if (valueType == STREAMING_MIN_UDP_PORT_IO_HANDLER_TYPE) {
+                mPref.edit().putString(SettingsActivity.PREFERENCE_RTP_MINPORT,
+                        value).commit();
+                System.putString(context.getContentResolver(),
+                        "streaming_min_udp_port", value);
+            } else if (valueType == STREAMING_CONNPROFILE_IO_HANDLER_TYPE) {
+                mPref.edit().putString(SettingsActivity.PREFERENCE_APN,
+                        value).commit();
+                System.putString(context.getContentResolver(),
+                        "apn", value);
+            }
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/ExtensionHelper.java b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
new file mode 100755
index 0000000..414520b
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/ExtensionHelper.java
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+*/
+package org.codeaurora.gallery3d.video;
+
+import android.content.Context;
+
+import com.android.gallery3d.app.MovieActivity;
+import org.codeaurora.gallery.R;
+
+import org.codeaurora.gallery3d.ext.ActivityHookerGroup;
+import org.codeaurora.gallery3d.ext.IActivityHooker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExtensionHelper {
+
+    public static IActivityHooker getHooker(final Context context) {
+
+        final ActivityHookerGroup group = new ActivityHookerGroup();
+        boolean loop = context.getResources().getBoolean(R.bool.loop);
+        boolean stereo = context.getResources().getBoolean(R.bool.stereo);
+        boolean streaming = context.getResources().getBoolean(R.bool.streaming);
+        boolean playlist = context.getResources().getBoolean(R.bool.playlist);
+        boolean speaker = context.getResources().getBoolean(R.bool.speaker);
+
+        if (loop == true) {
+            group.addHooker(new LoopVideoHooker()); // add it for common feature.
+        }
+        if (stereo == true) {
+            group.addHooker(new StereoAudioHooker()); // add it for common feature.
+        }
+        if (streaming == true) {
+            group.addHooker(new StreamingHooker());
+           // group.addHooker(new BookmarkHooker());
+        }
+        if (playlist == true) {
+            group.addHooker(new MovieListHooker()); // add it for common feature.
+        }
+        if (speaker == true) {
+            group.addHooker(new SpeakerHooker());
+        }
+        return group;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/IControllerRewindAndForward.java b/src/org/codeaurora/gallery3d/video/IControllerRewindAndForward.java
new file mode 100644
index 0000000..1fc7f70
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/IControllerRewindAndForward.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.codeaurora.gallery3d.video;
+
+import com.android.gallery3d.app.ControllerOverlay;
+import com.android.gallery3d.app.ControllerOverlay.Listener;
+
+///M: for CU rewind and forward
+public interface IControllerRewindAndForward extends ControllerOverlay {
+
+  interface IRewindAndForwardListener extends Listener {
+    void onStopVideo();
+    void onRewind();
+    void onForward();
+  }
+
+  boolean getPlayPauseEanbled();
+  boolean getTimeBarEanbled();
+  void setIListener(IRewindAndForwardListener listener);
+  void showControllerButtonsView(boolean canStop, boolean canRewind, boolean canForward);
+}
diff --git a/src/org/codeaurora/gallery3d/video/IVideoSnapshotListener.java b/src/org/codeaurora/gallery3d/video/IVideoSnapshotListener.java
new file mode 100644
index 0000000..b8675ce
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/IVideoSnapshotListener.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package org.codeaurora.gallery3d.video;
+
+public interface IVideoSnapshotListener {
+    void onVideoSnapshot();
+    boolean canVideoSnapshot();
+}
diff --git a/src/org/codeaurora/gallery3d/video/LoopVideoHooker.java b/src/org/codeaurora/gallery3d/video/LoopVideoHooker.java
new file mode 100644
index 0000000..ec660b9
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/LoopVideoHooker.java
@@ -0,0 +1,60 @@
+package org.codeaurora.gallery3d.video;
+
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.codeaurora.gallery.R;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+
+public class LoopVideoHooker extends MovieHooker {
+
+    private static final String TAG = "LoopVideoHooker";
+    private static final boolean LOG = false;
+    private static final int MENU_LOOP = 1;
+
+    private MenuItem mMenuLoopButton;
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        mMenuLoopButton = menu.add(0, getMenuActivityId(MENU_LOOP), 0, R.string.loop);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        updateLoop();
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch (getMenuOriginalId(item.getItemId())) {
+            case MENU_LOOP:
+                getPlayer().setLoop(!getPlayer().getLoop());
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void updateLoop() {
+        if (mMenuLoopButton != null) {
+            if (MovieUtils.isLocalFile(getMovieItem().getUri(), getMovieItem().getMimeType())) {
+                mMenuLoopButton.setVisible(true);
+            } else {
+                mMenuLoopButton.setVisible(false);
+            }
+            final boolean newLoop = getPlayer().getLoop();
+            if (newLoop) {
+                mMenuLoopButton.setTitle(R.string.single);
+                mMenuLoopButton.setIcon(R.drawable.ic_menu_unloop);
+            } else {
+                mMenuLoopButton.setTitle(R.string.loop);
+                mMenuLoopButton.setIcon(R.drawable.ic_menu_loop);
+            }
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/MovieHooker.java b/src/org/codeaurora/gallery3d/video/MovieHooker.java
new file mode 100644
index 0000000..a859d44
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/MovieHooker.java
@@ -0,0 +1,44 @@
+package org.codeaurora.gallery3d.video;
+
+import android.util.Log;
+
+import org.codeaurora.gallery3d.ext.ActivityHooker;
+import org.codeaurora.gallery3d.ext.IMovieItem;
+import org.codeaurora.gallery3d.ext.IMoviePlayer;
+
+public class MovieHooker extends ActivityHooker {
+
+    private static final String TAG = "MovieHooker";
+    private static final boolean LOG = false;
+    private IMovieItem mMovieItem;
+    private IMoviePlayer mPlayer;
+
+    @Override
+    public void setParameter(final String key, final Object value) {
+        super.setParameter(key, value);
+        if (LOG) {
+            Log.v(TAG, "setParameter(" + key + ", " + value + ")");
+        }
+        if (value instanceof IMovieItem) {
+            mMovieItem = (IMovieItem) value;
+            onMovieItemChanged(mMovieItem);
+        } else if (value instanceof IMoviePlayer) {
+            mPlayer = (IMoviePlayer) value;
+            onMoviePlayerChanged(mPlayer);
+        }
+    }
+
+    public IMovieItem getMovieItem() {
+        return mMovieItem;
+    }
+
+    public IMoviePlayer getPlayer() {
+        return mPlayer;
+    }
+
+    public void onMovieItemChanged(final IMovieItem item) {
+    }
+
+    public void onMoviePlayerChanged(final IMoviePlayer player) {
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/MovieListHooker.java b/src/org/codeaurora/gallery3d/video/MovieListHooker.java
new file mode 100644
index 0000000..1020981
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/MovieListHooker.java
@@ -0,0 +1,116 @@
+package org.codeaurora.gallery3d.video;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.codeaurora.gallery.R;
+import org.codeaurora.gallery3d.ext.IMovieItem;
+import org.codeaurora.gallery3d.ext.IMovieList;
+import org.codeaurora.gallery3d.ext.IMovieListLoader;
+import org.codeaurora.gallery3d.ext.IMovieListLoader.LoaderListener;
+import org.codeaurora.gallery3d.ext.MovieListLoader;
+
+public class MovieListHooker extends MovieHooker implements LoaderListener {
+    private static final String TAG = "MovieListHooker";
+    private static final boolean LOG = false;
+    
+    private static final int MENU_NEXT = 1;
+    private static final int MENU_PREVIOUS = 2;
+    
+    private MenuItem mMenuNext;
+    private MenuItem mMenuPrevious;
+    
+    private IMovieListLoader mMovieLoader;
+    private IMovieList mMovieList;
+    
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mMovieLoader = new MovieListLoader();
+        mMovieLoader.fillVideoList(getContext(), getIntent(), this, getMovieItem());
+    }
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mMovieLoader.cancelList();
+    }
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        if (mMovieList != null) { //list should be filled
+            if (mMovieLoader != null && mMovieLoader.isEnabledVideoList(getIntent())) {
+                mMenuPrevious = menu.add(0, getMenuActivityId(MENU_PREVIOUS), 0, R.string.previous);
+                mMenuNext = menu.add(0, getMenuActivityId(MENU_NEXT), 0, R.string.next);
+            }
+        }
+        return true;
+    }
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        updatePrevNext();
+        return true;
+    }
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch(getMenuOriginalId(item.getItemId())) {
+        case MENU_PREVIOUS:
+            if (mMovieList == null) {
+                return false;
+            }
+            getPlayer().startNextVideo(mMovieList.getPrevious(getMovieItem()));
+            return true;
+        case MENU_NEXT:
+            if (mMovieList == null) {
+                return false;
+            }
+            getPlayer().startNextVideo(mMovieList.getNext(getMovieItem()));
+            return true;
+        default:
+            return false;
+        }
+    }
+    
+    @Override
+    public void onMovieItemChanged(final IMovieItem item) {
+        super.onMovieItemChanged(item);
+        updatePrevNext();
+    }
+    
+    private void updatePrevNext() {
+        if (LOG) {
+            Log.v(TAG, "updatePrevNext()");
+        }
+        if (mMovieList != null && mMenuPrevious != null && mMenuNext != null) {
+            if (mMovieList.isFirst(getMovieItem()) && mMovieList.isLast(getMovieItem())) { //only one movie
+                mMenuNext.setVisible(false);
+                mMenuPrevious.setVisible(false);
+            } else {
+                mMenuNext.setVisible(true);
+                mMenuPrevious.setVisible(true);
+            }
+            if (mMovieList.isFirst(getMovieItem())) {
+                mMenuPrevious.setEnabled(false);
+            } else {
+                mMenuPrevious.setEnabled(true);
+            }
+            if (mMovieList.isLast(getMovieItem())) {
+                mMenuNext.setEnabled(false);
+            } else {
+                mMenuNext.setEnabled(true);
+            }
+        }
+    }
+    
+    @Override
+    public void onListLoaded(final IMovieList movieList) {
+        mMovieList = movieList;
+        getContext().invalidateOptionsMenu();
+        if (LOG) {
+            Log.v(TAG, "onListLoaded() " + (mMovieList != null ? mMovieList.size() : "null"));
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
new file mode 100644
index 0000000..4f23e81
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/MovieTitleHelper.java
@@ -0,0 +1,108 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteException;
+import android.net.Uri;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.util.Log;
+
+
+import java.io.File;
+
+public class MovieTitleHelper {
+    private static final String TAG = "MovieTitleHelper";
+    private static final boolean LOG = false;
+
+    public static String getTitleFromMediaData(final Context context, final Uri uri) {
+        String title = null;
+        Cursor cursor = null;
+        try {
+            String data = Uri.decode(uri.toString());
+            data = data.replaceAll("'", "''");
+            final String where = "_data LIKE '%" + data.replaceFirst("file:///", "") + "'";
+            cursor = context.getContentResolver().query(
+                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                    new String[] {
+                        OpenableColumns.DISPLAY_NAME
+                    }, where, null, null);
+            if (LOG) {
+                Log.v(
+                        TAG,
+                        "setInfoFromMediaData() cursor="
+                                + (cursor == null ? "null" : cursor.getCount()));
+            }
+            if (cursor != null && cursor.moveToFirst()) {
+                title = cursor.getString(0);
+            }
+        } catch (final SQLiteException ex) {
+            ex.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "setInfoFromMediaData() return " + title);
+        }
+        return title;
+    }
+
+    public static String getTitleFromDisplayName(final Context context, final Uri uri) {
+        String title = null;
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(uri,
+                    new String[] {
+                        OpenableColumns.DISPLAY_NAME
+                    }, null, null, null);
+            if (cursor != null && cursor.moveToFirst()) {
+                title = cursor.getString(0);
+            }
+        } catch (final SQLiteException ex) {
+            ex.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "getTitleFromDisplayName() return " + title);
+        }
+        return title;
+    }
+
+    public static String getTitleFromUri(final Uri uri) {
+        final String title = Uri.decode(uri.getLastPathSegment());
+        if (LOG) {
+            Log.v(TAG, "getTitleFromUri() return " + title);
+        }
+        return title;
+    }
+
+    public static String getTitleFromData(final Context context, final Uri uri) {
+        String title = null;
+        Cursor cursor = null;
+        try {
+            cursor = context.getContentResolver().query(uri,
+                    new String[] {
+                        "_data"
+                    }, null, null, null);
+            if (cursor != null && cursor.moveToFirst()) {
+                final File file = new File(cursor.getString(0));
+                title = file.getName();
+            }
+        } catch (final SQLiteException ex) {
+            ex.printStackTrace();
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "getTitleFromData() return " + title);
+        }
+        return title;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/ScreenModeManager.java b/src/org/codeaurora/gallery3d/video/ScreenModeManager.java
new file mode 100644
index 0000000..a1c04c6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/ScreenModeManager.java
@@ -0,0 +1,117 @@
+package org.codeaurora.gallery3d.video;
+
+import android.util.Log;
+
+import java.util.ArrayList;
+
+public class ScreenModeManager {
+    private static final String TAG = "ScreenModeManager";
+    private static final boolean LOG = false;
+    //support screen mode.
+    public static final int SCREENMODE_BIGSCREEN = 1;
+    public static final int SCREENMODE_FULLSCREEN = 2;
+    public static final int SCREENMODE_CROPSCREEN = 4;
+    public static final int SCREENMODE_ALL = 7;
+    
+    private int mScreenMode = SCREENMODE_BIGSCREEN;
+    private int mScreenModes = SCREENMODE_ALL;
+    
+    /**
+     * Enable specified screen mode list. 
+     * The screen mode's value determines the order of being shown. 
+     * <br>you can enable three screen modes by setting screenModes = 
+     * {@link #SCREENMODE_BIGSCREEN} | 
+     * {@link #SCREENMODE_FULLSCREEN} |
+     * {@link #SCREENMODE_CROPSCREEN} or 
+     * just enable two screen modes by setting screenModes = 
+     * {@link #SCREENMODE_BIGSCREEN} | 
+     * {@link #SCREENMODE_CROPSCREEN}.
+     * <br>If current screen mode is the last one of the ordered list, 
+     * then the next screen mode will be the first one of the ordered list.
+     * @param screenModes enabled screen mode list.
+     */
+    public void setScreenModes(final int screenModes) {
+        mScreenModes = (SCREENMODE_BIGSCREEN & screenModes)
+            | (SCREENMODE_FULLSCREEN & screenModes)
+            | (SCREENMODE_CROPSCREEN & screenModes);
+        if ((screenModes & SCREENMODE_ALL) == 0) {
+            mScreenModes = SCREENMODE_ALL;
+            Log.w(TAG, "wrong screenModes=" + screenModes + ". use default value " + SCREENMODE_ALL);
+        }
+        if (LOG) {
+            Log.v(TAG, "enableScreenMode(" + screenModes + ") mScreenModes=" + mScreenModes);
+        }
+    }
+    
+    /**
+     * Get the all screen modes of media controller.
+     * <br><b>Note:</b> it is not the video's current screen mode.
+     * @return the current screen modes.
+     */
+    public int getScreenModes() {
+        return mScreenModes;
+    }
+    
+    public void setScreenMode(final int curScreenMode) {
+        if (LOG) {
+            Log.v(TAG, "setScreenMode(" + curScreenMode + ")");
+        }
+        mScreenMode = curScreenMode;
+        for (final ScreenModeListener listener : mListeners) {
+            listener.onScreenModeChanged(curScreenMode);
+        }
+    }
+    
+    public int getScreenMode() {
+        if (LOG) {
+            Log.v(TAG, "getScreenMode() return " + mScreenMode);
+        }
+        return mScreenMode;
+    }
+    
+    public int getNextScreenMode() {
+        int mode = getScreenMode();
+        mode <<= 1;
+        if ((mode & mScreenModes) == 0) {
+            //not exist, find the right one
+            if (mode > mScreenModes) {
+                mode = 1;
+            }
+            while ((mode & mScreenModes) == 0) {
+                mode <<= 1;
+                if (mode > mScreenModes) {
+                    throw new RuntimeException("wrong screen mode = " + mScreenModes);
+                }
+            }
+        }
+        if (LOG) {
+            Log.v(TAG, "getNextScreenMode() = " + mode);
+        }
+        return mode;
+    }
+    
+    private final ArrayList<ScreenModeListener> mListeners = new ArrayList<ScreenModeListener>();
+    public void addListener(final ScreenModeListener l) {
+        if (!mListeners.contains(l)) {
+            mListeners.add(l);
+        }
+        if (LOG) {
+            Log.v(TAG, "addListener(" + l + ")");
+        }
+    }
+    
+    public void removeListener(final ScreenModeListener l) {
+        mListeners.remove(l);
+        if (LOG) {
+            Log.v(TAG, "removeListener(" + l + ")");
+        }
+    }
+    
+    public void clear() {
+        mListeners.clear();
+    }
+    
+    public interface ScreenModeListener {
+        void onScreenModeChanged(int newMode);
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/SettingsActivity.java b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
new file mode 100755
index 0000000..bf7b7d7
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/SettingsActivity.java
@@ -0,0 +1,300 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.provider.Settings;
+import android.provider.Settings.System;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.method.DigitsKeyListener;
+import android.util.Log;
+import android.view.MenuItem;
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.common.ApiHelper;
+import com.android.gallery3d.common.ApiHelper.SystemProperties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SettingsActivity extends AbstractPermissionPreferenceActivity {
+
+    private static final String LOG_TAG = "SettingsActivity";
+
+    public  static final String PREFERENCE_RTP_MINPORT = "rtp_min_port";
+    public  static final String PREFERENCE_RTP_MAXPORT = "rtp_max_port";
+    private static final String PREFERENCE_KEEP_ALIVE_INTERVAL_SECOND = "keep_alive_interval_second";
+    private static final String PREFERENCE_CACHE_MIN_SIZE = "cache_min_size";
+    private static final String PREFERENCE_CACHE_MAX_SIZE = "cache_max_size";
+    public  static final String PREFERENCE_BUFFER_SIZE = "buffer_size";
+    public  static final String PREFERENCE_APN_CATEGORY = "apn_category";
+    public  static final String PREFERENCE_APN = "apn";
+    private static final String PACKAGE_NAME  = "com.android.settings";
+
+    private static final int DEFAULT_RTP_MINPORT = 8192;
+    private static final int DEFAULT_RTP_MAXPORT = 65535;
+    private static final int DEFAULT_CACHE_MIN_SIZE = 4 * 1024 * 1024;
+    private static final int DEFAULT_CACHE_MAX_SIZE = 20 * 1024 * 1024;
+    private static final int DEFAULT_KEEP_ALIVE_INTERVAL_SECOND = 15;
+
+    private static final int RTP_MIN_PORT = 1;
+    private static final int RTP_MAX_PORT = 2;
+    private static final int BUFFER_SIZE  = 3;
+    private static final boolean DBG = true;
+    private static final String TAG = SettingsActivity.class.getSimpleName();
+
+    private SharedPreferences  mPref;
+    private EditTextPreference mRtpMinPort;
+    private EditTextPreference mRtpMaxPort;
+    private EditTextPreference mBufferSize;
+    private PreferenceCategory mApnCategory;
+    private PreferenceScreen   mApn;
+
+    private static final int    SELECT_APN = 1;
+    public  static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
+    private static final Uri    PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
+    private static final int    COLUMN_ID_INDEX = 0;
+    private static final int    NAME_INDEX = 1;
+
+    private boolean mUseNvOperatorForEhrpd = SystemProperties.getBoolean(
+            "persist.radio.use_nv_for_ehrpd", false);
+
+    private SubscriptionManager mSubscriptionManager;
+    private List<SubscriptionInfo> mActiveSubInfos;
+
+    @Override
+    protected void onGetPermissionsSuccess() {
+        init();
+    }
+
+    @Override
+    protected void onGetPermissionsFailure() {
+        finish();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.rtsp_settings_preferences);
+
+        mPref = getPreferenceScreen().getSharedPreferences();
+        mRtpMinPort = (EditTextPreference) findPreference(PREFERENCE_RTP_MINPORT);
+        mRtpMaxPort = (EditTextPreference) findPreference(PREFERENCE_RTP_MAXPORT);
+        mBufferSize = (EditTextPreference) findPreference(PREFERENCE_BUFFER_SIZE);
+        mApnCategory = (PreferenceCategory) findPreference(PREFERENCE_APN_CATEGORY);
+        mApn = (PreferenceScreen) findPreference(PREFERENCE_APN);
+
+        setPreferenceListener(RTP_MIN_PORT, mRtpMinPort);
+        setPreferenceListener(RTP_MAX_PORT, mRtpMaxPort);
+        setPreferenceListener(BUFFER_SIZE, mBufferSize);
+        setApnListener();
+
+        ActionBar ab = getActionBar();
+        ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+        ab.setDisplayHomeAsUpEnabled(true);
+        ab.setTitle(R.string.setting);
+
+        if (isPermissionGranted()) {
+            init();
+        }
+    }
+
+    private void init() {
+        mSubscriptionManager = SubscriptionManager.from(this);
+        try{
+            mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+        }catch (Exception e) {
+            Log.e(TAG,e.toString());
+            mSubscriptionManager = null;
+            return;
+        }
+        // Initialize mActiveSubInfo
+        int max = mSubscriptionManager.getActiveSubscriptionInfoCountMax();
+        mActiveSubInfos = new ArrayList<SubscriptionInfo>(max);
+
+        initializeSubscriptions();
+
+        if (!hasActiveSubscriptions() && mApnCategory != null && mApn != null) {
+            ((PreferenceGroup)mApnCategory).removePreference(mApn);
+            getPreferenceScreen().removePreference(mApnCategory);
+
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        if (null != mSubscriptionManager) {
+            mSubscriptionManager
+                    .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
+        }
+    }
+
+    private final SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangeListener
+            = new SubscriptionManager.OnSubscriptionsChangedListener() {
+        @Override
+        public void onSubscriptionsChanged() {
+            if (DBG) Log.i(TAG, "onSubscriptionsChanged:");
+            initializeSubscriptions();
+            if (hasActiveSubscriptions()) {
+                getPreferenceScreen().addPreference(mApnCategory);
+                mApnCategory.addPreference(mApn);
+            } else{
+                ((PreferenceGroup)mApnCategory).removePreference(mApn);
+                getPreferenceScreen().removePreference(mApnCategory);
+            }
+        }
+    };
+
+    private void initializeSubscriptions() {
+        if (isDestroyed()) { // Process preferences in activity only if its not destroyed
+            return;
+        }
+        if (DBG) Log.i(TAG, "initializeSubscriptions:+");
+
+        // Before updating the the active subscription list check
+        // if tab updating is needed as the list is changing.
+         List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+
+        // Update to the active subscription list
+        mActiveSubInfos.clear();
+        if (sil != null) {
+            mActiveSubInfos.addAll(sil);
+        }
+
+        if (DBG) Log.i(TAG, "initializeSubscriptions:-");
+    }
+
+    private boolean hasActiveSubscriptions() {
+        return mActiveSubInfos.size() > 0;
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == SELECT_APN) {
+            setResult(resultCode);
+            finish();
+            Log.w(LOG_TAG, "onActivityResult requestCode = " + requestCode);
+        }
+
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // TODO Auto-generated method stub
+        if (item.getItemId() == android.R.id.home) {
+            finish();
+        }
+        return true;
+    }
+
+    private String getOperatorNumericSelection() {
+        String[] mccmncs = getOperatorNumeric();
+        String where;
+        where = (mccmncs[0] != null) ? "numeric=\"" + mccmncs[0] + "\"" : "";
+        where += (mccmncs[1] != null) ? " or numeric=\"" + mccmncs[1] + "\"" : "";
+        Log.d(LOG_TAG, "getOperatorNumericSelection: " + where);
+        return where;
+    }
+
+    private String[] getOperatorNumeric() {
+        ArrayList<String> result = new ArrayList<String>();
+        if (mUseNvOperatorForEhrpd) {
+            String mccMncForEhrpd = SystemProperties.get("ro.cdma.home.operator.numeric", null);
+            if (mccMncForEhrpd != null && mccMncForEhrpd.length() > 0) {
+                result.add(mccMncForEhrpd);
+            }
+        }
+
+        TelephonyManager manager = (TelephonyManager) getApplicationContext()
+                .getSystemService(Context.TELEPHONY_SERVICE);
+        String mccMncFromSim = manager.getSimOperator();
+        if (mccMncFromSim != null && mccMncFromSim.length() > 0) {
+            result.add(mccMncFromSim);
+        }
+        return result.toArray(new String[2]);
+    }
+
+    private void setPreferenceListener(final int which, final EditTextPreference etp) {
+
+        final String DIGITS_ACCEPTABLE = "0123456789";
+        String summaryStr = "";
+        String preferStr  = "";
+
+        switch (which) {
+            case RTP_MIN_PORT:
+                preferStr = mPref.getString(PREFERENCE_RTP_MINPORT,
+                        Integer.toString(DEFAULT_RTP_MINPORT));
+                summaryStr = "streaming_min_udp_port";
+                break;
+            case RTP_MAX_PORT:
+                preferStr = mPref.getString(PREFERENCE_RTP_MAXPORT,
+                        Integer.toString(DEFAULT_RTP_MAXPORT));
+                summaryStr = "streaming_max_udp_port";
+                break;
+            case BUFFER_SIZE:
+                preferStr = mPref.getString(PREFERENCE_BUFFER_SIZE,
+                        Integer.toString(DEFAULT_CACHE_MAX_SIZE));
+                break;
+            default:
+                return;
+
+        }
+
+        final String summaryString = summaryStr;
+        etp.getEditText().setKeyListener(DigitsKeyListener.getInstance(DIGITS_ACCEPTABLE));
+        etp.setSummary(preferStr);
+        etp.setText(preferStr);
+        etp.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+            public boolean onPreferenceChange(Preference preference, Object newValue) {
+                final String summary = newValue.toString();
+                final int value;
+                try {
+                    value = Integer.valueOf(summary);
+                } catch (NumberFormatException e) {
+                    Log.e(LOG_TAG, "NumberFormatException");
+                    return false;
+                }
+                etp.setSummary(summary);
+                etp.setText(summary);
+                Log.d(LOG_TAG, "z66/z82 summary = " + summary);
+                return true;
+            }
+        });
+
+    }
+
+    private void setApnListener() {
+        final String SUBSCRIPTION_KEY = "subscription";
+        final String SUB_ID = "sub_id";
+        mApn.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+            public boolean onPreferenceClick(Preference preference) {
+                Intent intent = new Intent(Settings.ACTION_APN_SETTINGS);
+                int subscription = 0;
+                try {
+                    subscription = Settings.Global.getInt(
+                            SettingsActivity.this.getContentResolver(),
+                            ApiHelper.MULTI_SIM_DATA_CALL_SUBSCRIPTION);
+                } catch (Exception e) {
+                    Log.d("SettingActivity", "Can't get subscription for Exception: " + e);
+                } finally {
+                    intent.putExtra(SUBSCRIPTION_KEY, subscription);
+                    intent.putExtra(SUB_ID, subscription);
+                }
+                startActivityForResult(intent, SELECT_APN);
+                return true;
+            }
+        });
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/SpeakerHooker.java b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java
new file mode 100755
index 0000000..3ba641e
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/SpeakerHooker.java
@@ -0,0 +1,220 @@
+/*
+Copyright (c) 2014,2017 The Linux Foundation. All rights reserved.
+
+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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+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.
+*/
+package org.codeaurora.gallery3d.video;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.common.ApiHelper.AudioSystem;
+
+public class SpeakerHooker extends MovieHooker {
+
+    private static final int MENU_SPEAKER = 1;
+
+    private AudioManager mAudioManager;
+
+    private MenuItem mMenuSpeakerButton;
+
+    private static boolean mIsHeadsetOn = false;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        initAudioManager();
+    }
+
+    private void initAudioManager() {
+        if (mAudioManager == null) {
+            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        turnSpeakerOff();
+        super.onDestroy();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        registerHeadSetReceiver();
+    }
+
+    private void registerHeadSetReceiver() {
+        final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
+        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
+        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+        intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
+        getContext().registerReceiver(mHeadSetReceiver, intentFilter);
+    }
+
+    @Override
+    public void onPause() {
+        unregisterHeadSetReceiver();
+        super.onPause();
+    }
+
+    private void unregisterHeadSetReceiver() {
+        try {
+            getContext().unregisterReceiver(mHeadSetReceiver);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    private final BroadcastReceiver mHeadSetReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (mAudioManager == null) {
+                initAudioManager();
+            }
+            if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
+                mIsHeadsetOn = (intent.getIntExtra("state", 0) == 1)
+                        || mAudioManager.isBluetoothA2dpOn();
+            } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
+                    || action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+                final BluetoothClass bc = ((BluetoothDevice)
+                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE))
+                                .getBluetoothClass();
+                if (bc == null) return;
+                final int deviceClass = bc.getDeviceClass();
+                if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES)
+                        || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) {
+                    mIsHeadsetOn = action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)
+                            || mAudioManager.isWiredHeadsetOn();
+                }
+            } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
+                mIsHeadsetOn = false;
+            }
+            updateSpeakerButton();
+            if (!mIsHeadsetOn) {
+                turnSpeakerOff();
+            }
+        }
+    };
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        mMenuSpeakerButton = menu.add(0, getMenuActivityId(MENU_SPEAKER), 0, R.string.speaker_on);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch (getMenuOriginalId(item.getItemId())) {
+            case MENU_SPEAKER:
+                changeSpeakerState();
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void changeSpeakerState() {
+        if (isSpeakerOn()) {
+            turnSpeakerOff();
+        } else {
+            if (mAudioManager == null) {
+                initAudioManager();
+            }
+            boolean isBluetoothOn = mAudioManager.isBluetoothA2dpOn() ||
+                    mAudioManager.isBluetoothScoOn();
+            if (mIsHeadsetOn || isBluetoothOn) {
+                turnSpeakerOn();
+            } else {
+                Toast.makeText(getContext(), getContext().getString(R.string.speaker_need_headset),
+                        Toast.LENGTH_SHORT).show();
+            }
+        }
+        updateSpeakerButton();
+    }
+
+    private void turnSpeakerOn() {
+        if (mAudioManager == null) {
+            initAudioManager();
+        }
+        boolean isBluetoothOn = mAudioManager.isBluetoothA2dpOn() ||
+                mAudioManager.isBluetoothScoOn();
+        if (isBluetoothOn) {
+            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                    AudioSystem.FORCE_NO_BT_A2DP);
+        } else {
+            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                    AudioSystem.FORCE_SPEAKER);
+
+        }
+    }
+
+    private void turnSpeakerOff() {
+        if (mAudioManager == null) {
+            initAudioManager();
+        }
+        AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                AudioSystem.FORCE_NONE);
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        updateSpeakerButton();
+        return true;
+    }
+
+    private void updateSpeakerButton() {
+        if (mMenuSpeakerButton != null) {
+            if (isSpeakerOn()) {
+                mMenuSpeakerButton.setTitle(R.string.speaker_off);
+            } else {
+                mMenuSpeakerButton.setTitle(R.string.speaker_on);
+            }
+        }
+    }
+
+    private boolean isSpeakerOn() {
+        return (AudioSystem.FORCE_SPEAKER
+                == AudioSystem.getForceUse(AudioSystem.FOR_MEDIA)) ||
+                (AudioSystem.FORCE_NO_BT_A2DP
+                        == AudioSystem.getForceUse(AudioSystem.FOR_MEDIA));
+    }
+
+}
diff --git a/src/org/codeaurora/gallery3d/video/StepOptionDialogFragment.java b/src/org/codeaurora/gallery3d/video/StepOptionDialogFragment.java
new file mode 100644
index 0000000..50bd8a6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/StepOptionDialogFragment.java
@@ -0,0 +1,83 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+/** M: use DialogFragment to show Dialog */
+public class StepOptionDialogFragment extends DialogFragment implements
+        DialogInterface.OnClickListener{
+
+    private static final String KEY_ITEM_ARRAY = "itemArray";
+    private static final String KEY_TITLE = "title";
+    private static final String KEY_DEFAULT_SELECT = "nowSelect";
+    private DialogInterface.OnClickListener mClickListener = null;
+
+    /**
+     * M: create a instance of SelectDialogFragment
+     * 
+     * @param itemArrayID
+     *            the resource id array of strings that show in list
+     * @param sufffixArray
+     *            the suffix array at the right of list item
+     * @param titleID
+     *            the resource id of title string
+     * @param nowSelect
+     *            the current select item index
+     * @return the instance of SelectDialogFragment
+     */
+    public static StepOptionDialogFragment newInstance(int[] itemArrayID,
+            int titleID, int nowSelect) {
+        StepOptionDialogFragment frag = new StepOptionDialogFragment();
+        Bundle args = new Bundle();
+        args.putIntArray(KEY_ITEM_ARRAY, itemArrayID);
+        args.putInt(KEY_TITLE, titleID);
+        args.putInt(KEY_DEFAULT_SELECT, nowSelect);
+        frag.setArguments(args);
+        return frag;
+    }
+
+    @Override
+    /**
+     * M: create a select dialog
+     */
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        Bundle args = getArguments();
+        final String title = getString(args.getInt(KEY_TITLE));
+        final int[] itemArrayID = args.getIntArray(KEY_ITEM_ARRAY);
+        int arraySize = itemArrayID.length;
+        CharSequence[] itemArray = new CharSequence[arraySize];
+        for (int i = 0; i < arraySize; i++) {
+            itemArray[i] = getString(itemArrayID[i]);
+        }
+
+        AlertDialog.Builder builder = null;
+        int nowSelect = args.getInt(KEY_DEFAULT_SELECT);
+        builder = new AlertDialog.Builder(getActivity());
+        builder.setTitle(title).setSingleChoiceItems(itemArray, nowSelect, this)
+                .setNegativeButton(getString(android.R.string.cancel), null);
+        return builder.create();
+    }
+
+    @Override
+    /**
+     * M: the process of select an item
+     */
+    public void onClick(DialogInterface arg0, int arg1) {
+        if (null != mClickListener) {
+            mClickListener.onClick(arg0, arg1);
+        }
+    }
+
+    /**
+     * M: set listener of click items
+     * 
+     * @param listener
+     *            the listener to be set
+     */
+    public void setOnClickListener(DialogInterface.OnClickListener listener) {
+        mClickListener = listener;
+    }
+}
\ No newline at end of file
diff --git a/src/org/codeaurora/gallery3d/video/StepOptionSettingsHooker.java b/src/org/codeaurora/gallery3d/video/StepOptionSettingsHooker.java
new file mode 100644
index 0000000..3291ad6
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/StepOptionSettingsHooker.java
@@ -0,0 +1,41 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Intent;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.codeaurora.gallery.R;
+import com.android.gallery3d.app.MovieActivity;
+import org.codeaurora.gallery3d.ext.ActivityHooker;
+import org.codeaurora.gallery3d.video.VideoSettingsActivity;
+
+public class StepOptionSettingsHooker extends ActivityHooker {
+    private static final int MENU_STEP_OPTION_SETTING = 1;
+    private MenuItem mMenuStepOption;
+    
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        mMenuStepOption = menu.add(0, getMenuActivityId(MENU_STEP_OPTION_SETTING), 0, R.string.settings);
+        return true;
+    }
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        return true;
+    }
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch(getMenuOriginalId(item.getItemId())) {
+        case MENU_STEP_OPTION_SETTING:
+            //start activity
+            Intent mIntent = new Intent();
+            mIntent.setClass(getContext(), VideoSettingsActivity.class);
+            getContext().startActivity(mIntent);
+            return true;
+        default:
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/org/codeaurora/gallery3d/video/StereoAudioHooker.java b/src/org/codeaurora/gallery3d/video/StereoAudioHooker.java
new file mode 100755
index 0000000..a660480
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/StereoAudioHooker.java
@@ -0,0 +1,118 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import org.codeaurora.gallery.R;
+
+public class StereoAudioHooker extends MovieHooker {
+    private static final String TAG = "StereoAudioHooker";
+    private static final boolean LOG = false;
+
+    private static final int MENU_STEREO_AUDIO = 1;
+    private MenuItem mMenuStereoAudio;
+
+    private static final String KEY_STEREO = "EnableStereoOutput";
+    private boolean mSystemStereoAudio;
+    private boolean mCurrentStereoAudio;
+    private boolean mIsInitedStereoAudio;
+    private AudioManager mAudioManager;
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        enableStereoAudio();
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        restoreStereoAudio();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        mMenuStereoAudio = menu.add(0, getMenuActivityId(MENU_STEREO_AUDIO), 0,
+                R.string.single_track);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        updateStereoAudioIcon();
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        if(getMenuOriginalId(item.getItemId()) == MENU_STEREO_AUDIO) {
+            mCurrentStereoAudio = !mCurrentStereoAudio;
+            setStereoAudio(mCurrentStereoAudio);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean getStereoAudio() {
+        boolean isstereo = false;
+        if (mAudioManager == null) {
+            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+        }
+        final String stereo = mAudioManager.getParameters(KEY_STEREO);
+        final String key = KEY_STEREO + "=1";
+        if (stereo != null && stereo.indexOf(key) > -1) {
+            isstereo = true;
+        } else {
+            isstereo = false;
+        }
+        if (LOG) {
+            Log.v(TAG, "getStereoAudio() isstereo=" + isstereo + ", stereo=" + stereo
+                    + ", key=" + key);
+        }
+        return isstereo;
+    }
+
+    private void setStereoAudio(final boolean flag) {
+        final String value = KEY_STEREO + "=" + (flag ? "1" : "0");
+        if (mAudioManager == null) {
+            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
+        }
+        mAudioManager.setParameters(value);
+        if (LOG) {
+            Log.v(TAG, "setStereoAudio(" + flag + ") value=" + value);
+        }
+    }
+
+    private void updateStereoAudioIcon() {
+        if (mMenuStereoAudio != null) {
+            mMenuStereoAudio.setTitle(mCurrentStereoAudio?R.string.single_track:R.string.stereo);
+            mMenuStereoAudio.setIcon(mCurrentStereoAudio?R.drawable.ic_menu_single_track:R.drawable.ic_menu_stereo);
+        }
+    }
+
+    private void enableStereoAudio() {
+        if (LOG) {
+            Log.v(TAG, "enableStereoAudio() mIsInitedStereoAudio=" + mIsInitedStereoAudio
+                    + ", mCurrentStereoAudio=" + mCurrentStereoAudio);
+        }
+        mSystemStereoAudio = getStereoAudio();
+        if (!mIsInitedStereoAudio) {
+            mCurrentStereoAudio = mSystemStereoAudio;
+            mIsInitedStereoAudio = true;
+        } else {
+            // restore old stereo type
+            setStereoAudio(mCurrentStereoAudio);
+        }
+        updateStereoAudioIcon();
+    }
+
+    private void restoreStereoAudio() {
+        setStereoAudio(mSystemStereoAudio);
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/StreamingHooker.java b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
new file mode 100755
index 0000000..b8b1136
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/StreamingHooker.java
@@ -0,0 +1,86 @@
+package org.codeaurora.gallery3d.video;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.net.Uri;
+import android.provider.Browser;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.Toast;
+
+import org.codeaurora.gallery.R;
+import org.codeaurora.gallery3d.ext.MovieUtils;
+
+public class StreamingHooker extends MovieHooker {
+    private static final String TAG = "StreamingHooker";
+    private static final boolean LOG = false;
+
+    private static final String ACTION_STREAMING = "org.codeaurora.settings.streaming";
+    private static final int MENU_INPUT_URL = 1;
+    private static final int MENU_SETTINGS = 2;
+    private static final int MENU_DETAIL = 3;
+
+    public static final String KEY_LOGO_BITMAP = "logo-bitmap";
+
+    @Override
+    public boolean onCreateOptionsMenu(final Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        // when in rtsp streaming type, generally it only has one uri.
+        menu.add(0, getMenuActivityId(MENU_INPUT_URL), 0, R.string.input_url);
+        menu.add(0, getMenuActivityId(MENU_SETTINGS), 0, R.string.streaming_settings);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(final Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(final MenuItem item) {
+        super.onOptionsItemSelected(item);
+        switch (getMenuOriginalId(item.getItemId())) {
+            case MENU_INPUT_URL:
+                gotoInputUrl();
+                return true;
+            case MENU_SETTINGS:
+                gotoSettings();
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    private void gotoInputUrl() {
+        final String APN_NAME = getClass().getName();
+        final String URI_STR = "about:blank";
+        final String EXTRA_NAME = "inputUrl";
+
+        final Intent intent = new Intent();
+        intent.setAction(Intent.ACTION_VIEW);
+        intent.setData(Uri.parse(URI_STR));
+        intent.putExtra(EXTRA_NAME, true);
+        intent.putExtra(Browser.EXTRA_APPLICATION_ID, APN_NAME);
+
+        try {
+            getContext().startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(getContext(),
+                    R.string.fail_to_load, Toast.LENGTH_LONG).show();
+        }
+
+        if (LOG) {
+            Log.v(TAG, "gotoInputUrl() appName=" + APN_NAME);
+        }
+    }
+
+    private void gotoSettings() {
+        final Intent intent = new Intent(ACTION_STREAMING);
+        getContext().startActivity(intent);
+        if (LOG) {
+            Log.v(TAG, "gotoInputUrl()");
+        }
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/VideoSettingsActivity.java b/src/org/codeaurora/gallery3d/video/VideoSettingsActivity.java
new file mode 100644
index 0000000..ad73765
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/VideoSettingsActivity.java
@@ -0,0 +1,181 @@
+package org.codeaurora.gallery3d.video;
+
+import android.app.ListActivity;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.codeaurora.gallery.R;
+
+public class VideoSettingsActivity extends ListActivity {
+    private String OPTION_NAME = "option_name";
+    private String OPTION_DESC = "option_desc";
+    private String DIALOG_TAG_SELECT_STEP_OPTION = "step_option_dialog";
+    private static int[] sStepOptionArray = null;
+    private static final int STEP_OPTION_THREE_SECOND = 0;
+    private static final int STEP_OPTION_SIX_SECOND = 1;
+    private static final String SELECTED_STEP_OPTION = "selected_step_option";
+    private static final String VIDEO_PLAYER_DATA = "video_player_data";
+    private int mSelectedStepOption = -1;
+    private SharedPreferences mPrefs = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ActionBar actionBar = getActionBar();
+        actionBar.setTitle(getResources().getString(R.string.settings));
+        setContentView(R.layout.setting_list);
+        ArrayList<HashMap<String, Object>> arrlist = new ArrayList<HashMap<String, Object>>(1);
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put(OPTION_NAME, getString(R.string.setp_option_name));
+        map.put(OPTION_DESC, getString(R.string.step_option_desc));
+        arrlist.add(map);
+        SimpleAdapter adapter = new SimpleAdapter(this, arrlist, android.R.layout.simple_list_item_2,
+                new String[] { OPTION_NAME, OPTION_DESC }, new int[] {
+                android.R.id.text1,  android.R.id.text2});
+        setListAdapter(adapter);
+        restoreStepOptionSettings();
+    }
+    
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        storeStepOptionSettings();
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        restoreDialogFragment();
+        restoreStepOptionSettings();
+    }
+    
+    
+
+    @Override
+    protected void onDestroy() {
+        // TODO Auto-generated method stub
+        storeStepOptionSettings();
+        super.onDestroy();
+    }
+
+    @Override
+    protected void onListItemClick(ListView arg0, View arg1, int arg2, long arg3) {
+        switch (arg2) {
+        case 0:
+            DialogFragment newFragment = null;
+            FragmentManager fragmentManager = getFragmentManager();
+            removeOldFragmentByTag(DIALOG_TAG_SELECT_STEP_OPTION);
+            newFragment = StepOptionDialogFragment.newInstance(getStepOptionIDArray(),
+                    R.string.setp_option_name, mSelectedStepOption);
+            ((StepOptionDialogFragment) newFragment).setOnClickListener(mStepOptionSelectedListener);
+            newFragment.show(fragmentManager, DIALOG_TAG_SELECT_STEP_OPTION);
+            break;
+        default:
+            break;
+        }
+    }
+    
+    private int[] getStepOptionIDArray() {
+        int[] stepOptionIDArray = new int[2];
+        stepOptionIDArray[STEP_OPTION_THREE_SECOND] = R.string.setp_option_three_second;
+        stepOptionIDArray[STEP_OPTION_SIX_SECOND] = R.string.setp_option_six_second;
+        sStepOptionArray  = new int[2];
+        sStepOptionArray[0] = STEP_OPTION_THREE_SECOND;
+        sStepOptionArray[1] = STEP_OPTION_SIX_SECOND;
+        return stepOptionIDArray;
+    }
+
+    private DialogInterface.OnClickListener mStepOptionSelectedListener = new DialogInterface.OnClickListener() {
+        @Override
+        public void onClick(DialogInterface dialog, int whichItemSelect) {
+            setSelectedStepOption(whichItemSelect);
+            dialog.dismiss();
+        }
+    };
+    
+    public void setSelectedStepOption(int which) {
+        mSelectedStepOption = getSelectedStepOption(which);
+    }
+    
+    static int getSelectedStepOption(int which) {
+        return sStepOptionArray[which];
+    }
+    
+    /**
+     * remove old DialogFragment
+     * 
+     * @param tag
+     *            the tag of DialogFragment to be removed
+     */
+    private void removeOldFragmentByTag(String tag) {
+        FragmentManager fragmentManager = getFragmentManager();
+        DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(tag);
+        if (null != oldFragment) {
+            oldFragment.dismissAllowingStateLoss();
+        }
+    }
+    
+    private void restoreDialogFragment() {
+        FragmentManager fragmentManager = getFragmentManager();
+        Fragment fragment = fragmentManager.findFragmentByTag(DIALOG_TAG_SELECT_STEP_OPTION);
+        if (null != fragment) {
+            ((StepOptionDialogFragment) fragment).setOnClickListener(mStepOptionSelectedListener);
+        }
+    }
+    
+    private void storeStepOptionSettings() {
+        if (null == mPrefs) {
+            mPrefs = getSharedPreferences(VIDEO_PLAYER_DATA, 0);
+        }
+        SharedPreferences.Editor ed = mPrefs.edit();
+        ed.clear();
+        ed.putInt(SELECTED_STEP_OPTION, mSelectedStepOption);
+        ed.commit();
+    }
+
+    private void restoreStepOptionSettings() {
+        if (null == mPrefs) {
+            mPrefs = getSharedPreferences(VIDEO_PLAYER_DATA, 0);
+        }
+        mSelectedStepOption = mPrefs.getInt(SELECTED_STEP_OPTION, STEP_OPTION_THREE_SECOND);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+        case android.R.id.home:
+            // The user clicked on the Messaging icon in the action bar. Take them back from
+            // wherever they came from
+            finish();
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java b/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java
new file mode 100644
index 0000000..82620df
--- /dev/null
+++ b/src/org/codeaurora/gallery3d/video/VideoSnapshotExt.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2016,2017 The Linux Foundation. All rights reserved.
+
+ * 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 Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * 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.
+ */
+
+package org.codeaurora.gallery3d.video;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.provider.MediaStore.Images;
+import android.provider.MediaStore.Images.ImageColumns;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import org.codeaurora.gallery.R;
+
+import com.android.gallery3d.app.GalleryActivity;
+import com.android.gallery3d.app.MovieControllerOverlay;
+import com.android.gallery3d.app.MovieControllerOverlayNew;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class VideoSnapshotExt implements IVideoSnapshotListener {
+    private static String TAG = "VideoSnapshotExt";
+    private static final boolean DEBUG = false;
+
+    private static final String FOLDER = Environment.getExternalStorageDirectory() +
+            File.separator + "Pictures" + File.separator + "VideoSnapshots";
+    private static final String FILE_PREFIX = "VideoSnapshot_";
+    private static final String FILE_EXT = ".jpg";
+    private static final String TIME_STAMP_NAME = "yyyyMMdd_HHmmss";
+    private static final int CONTENT_VALUES_SIZE = 9;
+
+    private CodeauroraVideoView mVideoView;
+    private Context mContext;
+    private ContentResolver mContentResolver;
+
+    @Override
+    public void onVideoSnapshot() {
+        if (canVideoSnap()) {
+            int currentPosition = mVideoView.getMediaPlayer().getCurrentPosition();
+            doVideoSnap(mVideoView.getUri(), currentPosition);
+        }
+    }
+
+    @Override
+    public boolean canVideoSnapshot() {
+        return canVideoSnap();
+    }
+
+    public void init(MovieControllerOverlay controller, CodeauroraVideoView videoView,
+                     boolean isLocalFile) {
+        mContext = videoView.getContext();
+        mContentResolver = mContext.getContentResolver();
+
+        mVideoView = videoView;
+        if (controller instanceof MovieControllerOverlayNew) {
+            ((MovieControllerOverlayNew) controller).showVideoSnapshotButton(isLocalFile);
+            ((MovieControllerOverlayNew) controller).setVideoSnapshotListener(this);
+        }
+    }
+
+    private boolean canVideoSnap() {
+        if (mVideoView.getMediaPlayer() == null) {
+            Log.w(TAG, "can't videoSnapshot because mMediaPlayer is null !");
+            return false;
+        }
+        return true;
+    }
+
+    private void doVideoSnap(Uri uri, int snapPosition) {
+        VideoSnapParameters parameters = new VideoSnapParameters(uri, snapPosition);
+        new VideoSnapTask().execute(parameters);
+    }
+
+    private class VideoSnapParameters {
+        private int mSnapPosition;
+        private Uri mUri;
+
+        /**
+         * @param snapPosition milliseconds
+         */
+        public VideoSnapParameters(Uri uri, int snapPosition) {
+            mUri = uri;
+            mSnapPosition = snapPosition;
+        }
+
+        public int getSnapPosition() {
+            return mSnapPosition;
+        }
+
+        public Uri getUri() {
+            return mUri;
+        }
+    }
+
+    private class VideoSnapTask extends AsyncTask<VideoSnapParameters, Void, Bitmap> {
+        SimpleDateFormat mDateFormat = new SimpleDateFormat(TIME_STAMP_NAME, Locale.getDefault());
+        @Override
+        protected Bitmap doInBackground(VideoSnapParameters... params) {
+            VideoSnapParameters parameters = params[0];
+            return doVideoSnap(parameters.getUri(), parameters.getSnapPosition());
+        }
+
+        @Override
+        protected void onPostExecute(Bitmap result) {
+            if (result != null) {
+                saveVideoSnap(mContentResolver, result);
+            }
+        }
+
+        private boolean isPositionValid(int currentPosition, long duration) {
+            return (currentPosition <= duration) && (currentPosition >= 0);
+        }
+
+        private Bitmap doVideoSnap(Uri videoUri, int snapPosition) {
+            MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+            if (videoUri == null || !URLUtil.isValidUrl(videoUri.toString())) {
+                return null;
+            }
+            retriever.setDataSource(mContext, videoUri);
+            String durationString =
+                    retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
+            long duration =
+                    (durationString == null) ? 0 : Long.parseLong(durationString); // milliseconds
+            if (DEBUG) {
+                Log.d(TAG, "doVideoSnap at " + snapPosition + "/" + duration);
+            }
+            if (isPositionValid(snapPosition, duration)) {
+                // convert ms to us.
+                Bitmap bitmap = retriever.getFrameAtTime(snapPosition * 1000,
+                        MediaMetadataRetriever.OPTION_CLOSEST);
+                if (bitmap == null) {
+                    Log.w(TAG, "frame cannot be retrieved. ");
+                } else {
+                    retriever.release();
+                    if (DEBUG) {
+                        Log.d(TAG, "retriever get frame resolution : " +
+                                bitmap.getHeight() + "x" + bitmap.getWidth());
+                    }
+                    Log.d(GalleryActivity.QSST, "video snapshot done");
+                    return bitmap;
+                }
+            }
+            retriever.release();
+            return null;
+        }
+
+        private void saveVideoSnap(ContentResolver resolver, Bitmap videoSnap) {
+            File folder = new File(FOLDER);
+            if (!folder.exists()) {
+                folder.mkdirs();
+            }
+
+            long dateTaken = System.currentTimeMillis();
+            String fileName = mDateFormat.format(new Date(dateTaken));
+            String fileTitle = FILE_PREFIX + fileName;
+            File file = new File(folder, fileTitle + FILE_EXT);
+
+            try {
+                FileOutputStream fos = new FileOutputStream(file);
+                videoSnap.compress(Bitmap.CompressFormat.JPEG, 85, fos);
+                fos.close();
+
+                addImage(resolver, file.getPath(), fileTitle, dateTaken, file.length(), 0,
+                        videoSnap.getWidth(), videoSnap.getHeight());
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private static void addImage(ContentResolver resolver, String path, String title, long date,
+                                 long size, int orientation, int width, int height) {
+        // Insert into MediaStore.
+        ContentValues values = new ContentValues(CONTENT_VALUES_SIZE);
+        values.put(ImageColumns.TITLE, title);
+        values.put(ImageColumns.DISPLAY_NAME, title + ".jpg");
+        values.put(ImageColumns.DATE_TAKEN, date);
+        values.put(ImageColumns.MIME_TYPE, "image/jpeg");
+        values.put(ImageColumns.ORIENTATION, orientation);
+        values.put(ImageColumns.DATA, path);
+        values.put(ImageColumns.SIZE, size);
+        values.put(ImageColumns.WIDTH, width);
+        values.put(ImageColumns.HEIGHT, height);
+
+        try {
+            resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);
+        } catch (Throwable th) {
+            Log.w(TAG, "Failed to write MediaStore" + th);
+        }
+    }
+}
diff --git a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
index e82d561..bee9560 100644
--- a/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/editors/EditorManager.java
@@ -17,9 +17,6 @@
 package com.android.gallery3d.filtershow.editors;
 
 import com.android.gallery3d.filtershow.EditorPlaceHolder;
-import com.android.gallery3d.filtershow.editors.BasicEditor;
-import com.android.gallery3d.filtershow.editors.EditorCurves;
-import com.android.gallery3d.filtershow.editors.EditorZoom;
 
 public class EditorManager {
 
@@ -36,6 +33,18 @@
         editorPlaceHolder.addEditor(new EditorRotate());
         editorPlaceHolder.addEditor(new EditorStraighten());
         editorPlaceHolder.addEditor(new EditorCrop());
+        editorPlaceHolder.addEditor(new BasicEditor());
+        editorPlaceHolder.addEditor(new ImageOnlyEditor());
+        editorPlaceHolder.addEditor(new EditorRedEye());
+        editorPlaceHolder.addEditor(new EditorDualCamera());
+        editorPlaceHolder.addEditor(new EditorDualCamFusion());
+        editorPlaceHolder.addEditor(new EditorDualCamSketch());
+        editorPlaceHolder.addEditor(new TrueScannerEditor());
+        editorPlaceHolder.addEditor(new HazeBusterEditor());
+        editorPlaceHolder.addEditor(new SeeStraightEditor());
+        editorPlaceHolder.addEditor(new EditorTruePortraitBasic());
+        editorPlaceHolder.addEditor(new EditorTruePortraitImageOnly());
+        editorPlaceHolder.addEditor(new EditorTruePortraitMask());
+        editorPlaceHolder.addEditor(new EditorTruePortraitFusion());
     }
-
 }
diff --git a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
index cde615e..bc3b625 100644
--- a/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
+++ b/src_pd/com/android/gallery3d/filtershow/filters/FiltersManager.java
@@ -20,7 +20,7 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 
-import com.android.gallery3d.R;
+import org.codeaurora.gallery.R;
 
 import java.util.ArrayList;
 import java.util.HashMap;
diff --git a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java b/src_pd/com/android/gallery3d/picasasource/PicasaSource.java
index 5e800e2..fce670b 100644
--- a/src_pd/com/android/gallery3d/picasasource/PicasaSource.java
+++ b/src_pd/com/android/gallery3d/picasasource/PicasaSource.java
@@ -136,12 +136,6 @@
 
     public static void showSignInReminder(Activity context) {/*do nothing*/}
 
-    public static void onPackageAdded(Context context, String packageName) {/*do nothing*/}
-
-    public static void onPackageRemoved(Context context, String packageName) {/*do nothing*/}
-
-    public static void onPackageChanged(Context context, String packageName) {/*do nothing*/}
-
     public static Dialog getVersionCheckDialog(Activity activity){
         return null;
     }
diff --git a/src_pd/com/android/gallery3d/util/IntentHelper.java b/src_pd/com/android/gallery3d/util/IntentHelper.java
index 8aebfc1..d0fb59a 100644
--- a/src_pd/com/android/gallery3d/util/IntentHelper.java
+++ b/src_pd/com/android/gallery3d/util/IntentHelper.java
@@ -15,17 +15,16 @@
  */
 package com.android.gallery3d.util;
 
-import android.content.Context;
 import android.content.Intent;
+import android.provider.MediaStore;
 
 public class IntentHelper {
 
-    public static Intent getCameraIntent(Context context) {
-        return new Intent(Intent.ACTION_MAIN)
-            .setClassName("com.android.camera2", "com.android.camera.CameraLauncher");
+    public static Intent getCameraIntent() {
+        return new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
     }
 
-    public static Intent getGalleryIntent(Context context) {
+    public static Intent getGalleryIntent() {
         return new Intent(Intent.ACTION_MAIN)
             .setClassName("com.android.gallery3d", "com.android.gallery3d.app.GalleryActivity");
     }