Merge changes I8ac518ce,I8392b4c3,I3bef3f75

* changes:
  Support for activity to opt-in/out of PiP form of multi-window.
  API for moving top activity in a stack to pinned stack.
  Added support for pinned stack.
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 8181f6c..4c1fc88 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -87,7 +87,7 @@
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"कलर ID पूर्वनिर्धारितदेखि प्रतिबन्धित छैन। अर्को कल: प्रतिबन्धित छ"</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"कलर ID पूर्वनिर्धारितको लागि रोकावट छैन। अर्को कल: रोकावट छैन"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"सेवाको व्यवस्था छैन।"</string>
-    <string name="CLIRPermanent" msgid="3377371145926835671">"तपाईं कलर ID सेटिङ परिवर्तन गर्न सक्नुहुन्न।"</string>
+    <string name="CLIRPermanent" msgid="3377371145926835671">"तपाईँ कलर ID सेटिङ परिवर्तन गर्न सक्नुहुन्न।"</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"प्रतिबन्धित पहुँच परिवर्तन भएको छ"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"डेटा सेवा रोकिएको छ।"</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"आपतकालीन सेवा रोकिएको छ।"</string>
@@ -198,7 +198,7 @@
     <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"तपाईंको TV बन्द हुनेछ।"</string>
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"तपाईँको घडी बन्द गरिने छ।"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"तपाईँको फोन बन्द हुने छ।"</string>
-    <string name="shutdown_confirm_question" msgid="2906544768881136183">"के तपाईं बन्द गर्न चाहनुहुन्छ?"</string>
+    <string name="shutdown_confirm_question" msgid="2906544768881136183">"के तपाईँ बन्द गर्न चाहनुहुन्छ?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"सुरक्षित मोडमा पुनःबुट गर्नुहोस्"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"सुरक्षित मोडमा तपाईँ पुनःबुट गर्न चाहनु हुन्छ? तपाईँले स्थापना गरेका सबै तेस्रो पक्षका अनुप्रयोगहरूलाई असक्षम गराउने छ।"</string>
     <string name="recent_tasks_title" msgid="3691764623638127888">"नयाँ"</string>
@@ -786,7 +786,7 @@
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"तपाईँको भ्वाइसमेल इनबक्समा सन्देश थप्नको लागि अनुप्रयोगलाई अनुमति दिन्छ।"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"भूस्थान अनुमतिहरू ब्राउजर परिवर्तन गर्नुहोस्"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ब्राउजरको भू-स्थान अनुमतिहरू परिमार्जन गर्न अनुप्रयोगलाई अनुमति दिन्छ। खराब अनुप्रयोगहरूले  स्थान सूचना मनपरी वेब साइटहरूमा पठाउने अनुमतिको लागि यसलाई प्रयोग गर्न सक्छन्।"</string>
-    <string name="save_password_message" msgid="767344687139195790">"के तपाईं ब्राउजरले यो पासवर्ड सम्झेको चाहनुहुन्छ?"</string>
+    <string name="save_password_message" msgid="767344687139195790">"के तपाईँ ब्राउजरले यो पासवर्ड सम्झेको चाहनुहुन्छ?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"अहिले होइन"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"सम्झनुहोस्"</string>
     <string name="save_password_never" msgid="8274330296785855105">"कहिल्यै पनि होइन"</string>
@@ -907,13 +907,13 @@
     <string name="aerr_process_silence" msgid="4226685530196000222">"साइलेन्स पुनःबुट नभएसम्म <xliff:g id="PROCESS">%1$s</xliff:g> बाट क्र्यास हुन्छ।"</string>
     <string name="anr_title" msgid="4351948481459135709"></string>
     <string name="anr_activity_application" msgid="1904477189057199066">"<xliff:g id="APPLICATION">%2$s</xliff:g>ले कार्य गरिरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
-    <string name="anr_activity_process" msgid="5776209883299089767">"गतिविधि <xliff:g id="ACTIVITY">%1$s</xliff:g> ले प्रतिक्रिया देखाइरहेको छैन।\n\nके तपाईं यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
+    <string name="anr_activity_process" msgid="5776209883299089767">"गतिविधि <xliff:g id="ACTIVITY">%1$s</xliff:g> ले प्रतिक्रिया देखाइरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
     <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> जवाफ दिइरहेको छैन। के तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
     <string name="anr_process" msgid="6513209874880517125">"प्रक्रिया <xliff:g id="PROCESS">%1$s</xliff:g>ले कार्य गरिरहेको छैन।\n\nके तपाईँ यसलाई बन्द गर्न चाहनु हुन्छ?"</string>
     <string name="force_close" msgid="8346072094521265605">"ठिक छ"</string>
     <string name="report" msgid="4060218260984795706">"रिपोर्ट गर्नुहोस्"</string>
     <string name="wait" msgid="7147118217226317732">"प्रतीक्षा गर्नुहोस्"</string>
-    <string name="webpage_unresponsive" msgid="3272758351138122503">"पृष्ठ गैर जिम्मेवारी भएको छ।\n\nके तपाईं यसलाई बन्द गर्न चाहनुहुन्छ?"</string>
+    <string name="webpage_unresponsive" msgid="3272758351138122503">"पृष्ठ गैर जिम्मेवारी भएको छ।\n\nके तपाईँ यसलाई बन्द गर्न चाहनुहुन्छ?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"अनुप्रयोग पुनः निर्देशीत"</string>
     <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> अहिले चलिरहेको छ।"</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> वास्तविक सुरुवात भएको थियो।"</string>
@@ -1103,7 +1103,7 @@
     <string name="deny" msgid="2081879885755434506">"अस्वीकार गर्नुहोस्"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"अनुरोध गरिएको अनुमति"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">\n"खाता <xliff:g id="ACCOUNT">%s</xliff:g>को लागि अनुरोध गरिएको अनुमति।"</string>
-    <string name="forward_intent_to_owner" msgid="1207197447013960896">"तपाईं तपाईँको कार्य प्रोफाइल बाहिर यो अनुप्रयोग प्रयोग गरिरहनु भएको छ"</string>
+    <string name="forward_intent_to_owner" msgid="1207197447013960896">"तपाईँ तपाईँको कार्य प्रोफाइल बाहिर यो अनुप्रयोग प्रयोग गरिरहनु भएको छ"</string>
     <string name="forward_intent_to_work" msgid="621480743856004612">"तपाईँ आफ्नो कार्य प्रोफाइलमा यो अनुप्रयोग प्रयोग गरिरहनु भएको छ"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"इनपुट विधि"</string>
     <string name="sync_binding_label" msgid="3687969138375092423">"सिङ्क गर्नुहोस्"</string>
@@ -1151,7 +1151,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"हो"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"होइन"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"सीमा नाघेकाहरू मेट्नुहोस्"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"त्यहाँ <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> मेटाइएका आइटमहरू छन् <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>को लागि, खाता <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>। तपाईं के गर्न चाहनु हुन्छ?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"त्यहाँ <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> मेटाइएका आइटमहरू छन् <xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>को लागि, खाता <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g>। तपाईँ के गर्न चाहनु हुन्छ?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"वस्तुहरू मेट्नुहोस्"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"मेटिएकाहरू पूर्ववत बनाउनुहोस्।"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"अहिलेको लागि केही नगर्नुहोस्"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 49a3862..aac6ba3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1414,7 +1414,7 @@
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Försök igen senare"</string>
     <string name="immersive_cling_title" msgid="8394201622932303336">"Visar på fullskärm"</string>
-    <string name="immersive_cling_description" msgid="3482371193207536040">"Dra nedåt från skärmens överkant för att avsluta."</string>
+    <string name="immersive_cling_description" msgid="3482371193207536040">"Svep nedåt från skärmens överkant för att avsluta."</string>
     <string name="immersive_cling_positive" msgid="5016839404568297683">"OK"</string>
     <string name="done_label" msgid="2093726099505892398">"Klart"</string>
     <string name="hour_picker_description" msgid="6698199186859736512">"Cirkelreglage för timmar"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 7cbf3d2..960a314 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -650,7 +650,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Yanlış PIN kodu."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Kilidi açmak için önce Menü\'ye, sonra 0\'a basın."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Acil durum numarası"</string>
-    <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Hizmet yok"</string>
+    <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Servis yok"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Ekran kilitli."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Kilidi açmak veya acil çağrı yapmak için Menü\'ye basın."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Kilidi açmak için Menü\'ye basın."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 5ae3e1e..8c0b816 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -650,7 +650,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"Mã PIN không chính xác."</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"Để mở khóa, hãy nhấn vào Menu sau đó nhấn 0."</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Số khẩn cấp"</string>
-    <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Không có dịch vụ nào"</string>
+    <string name="lockscreen_carrier_default" msgid="6169005837238288522">"Không có dịch vụ"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"Màn hình đã khóa."</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nhấn vào Menu để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Nhấn vào Menu để mở khóa."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 602f607..29b729a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -650,8 +650,7 @@
     <string name="keyguard_password_wrong_pin_code" msgid="2422225591006134936">"PIN码有误。"</string>
     <string name="keyguard_label_text" msgid="861796461028298424">"要解锁,请先按 MENU 再按 0。"</string>
     <string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"急救或报警电话"</string>
-    <!-- no translation found for lockscreen_carrier_default (6169005837238288522) -->
-    <skip />
+    <string name="lockscreen_carrier_default" msgid="6169005837238288522">"没有服务"</string>
     <string name="lockscreen_screen_locked" msgid="7288443074806832904">"屏幕已锁定。"</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"按 Menu 解锁或进行紧急呼救。"</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"按 MENU 解锁。"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 74c745b..400c822 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1288,6 +1288,10 @@
          device is data-only. -->
     <bool name="config_voice_capable">true</bool>
 
+    <!-- Flag indicating that an outbound call must have a call capable phone account
+         that has declared it can process the call's handle. -->
+    <bool name="config_requireCallCapableAccountForHandle">false</bool>
+
     <!-- Flag indicating if the user is notified when the mobile network access is restricted -->
     <bool name="config_user_notification_of_restrictied_mobile_access">true</bool>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3baddbb..951a825 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -275,6 +275,7 @@
   <java-symbol type="bool" name="config_ui_enableFadingMarquee" />
   <java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
   <java-symbol type="bool" name="config_voice_capable" />
+  <java-symbol type="bool" name="config_requireCallCapableAccountForHandle" />
   <java-symbol type="bool" name="config_user_notification_of_restrictied_mobile_access" />
   <java-symbol type="bool" name="config_wifiDisplaySupportsProtectedBuffers" />
   <java-symbol type="bool" name="preferences_prefer_dual_pane" />
diff --git a/libs/hwui/microbench/ShadowBench.cpp b/libs/hwui/microbench/ShadowBench.cpp
index bd51693..1b0f5ea 100644
--- a/libs/hwui/microbench/ShadowBench.cpp
+++ b/libs/hwui/microbench/ShadowBench.cpp
@@ -83,16 +83,15 @@
     ShadowTestData shadowData;
     createShadowTestData(&shadowData);
     SkPath path;
-    path.reset();
-    path.addRoundRect(SkRect::MakeLTRB(0, 0, 100, 100), 5, 5);
+    path.addRoundRect(SkRect::MakeWH(100, 100), 5, 5);
 
     StartBenchmarkTiming();
     for (int i = 0; i < iters; i++) {
-        std::unique_ptr<VertexBuffer> ambient(new VertexBuffer);
-        std::unique_ptr<VertexBuffer> spot(new VertexBuffer);
-        tessellateShadows(shadowData, true, path, ambient.get(), spot.get());
-        MicroBench::DoNotOptimize(ambient.get());
-        MicroBench::DoNotOptimize(spot.get());
+        VertexBuffer ambient;
+        VertexBuffer spot;
+        tessellateShadows(shadowData, true, path, &ambient, &spot);
+        MicroBench::DoNotOptimize(&ambient);
+        MicroBench::DoNotOptimize(&spot);
     }
     StopBenchmarkTiming();
 }
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 085df35..eba00a6 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<com.android.documentsui.DocListItem xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.documentsui.ListItem xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@drawable/item_doc_list_background"
@@ -137,4 +137,4 @@
 
     </LinearLayout>
 
-</com.android.documentsui.DocListItem>
+</com.android.documentsui.ListItem>
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk b/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk
new file mode 100644
index 0000000..8baadba
--- /dev/null
+++ b/packages/DocumentsUI/testing/TestDocumentsProvider/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := TestDocumentsProvider
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml b/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml
new file mode 100644
index 0000000..66988a1
--- /dev/null
+++ b/packages/DocumentsUI/testing/TestDocumentsProvider/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.documentsui.testing">
+    <application>
+        <provider android:name="TestDocumentsProvider"
+                android:authorities="com.android.documentsui.testing"
+                android:exported="true"
+                android:grantUriPermissions="true"
+                android:permission="android.permission.MANAGE_DOCUMENTS">
+            <intent-filter>
+                <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+            </intent-filter>
+        </provider>
+    </application>
+</manifest>
diff --git a/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java b/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java
new file mode 100644
index 0000000..63ff0de
--- /dev/null
+++ b/packages/DocumentsUI/testing/TestDocumentsProvider/src/com/android/documentsui/testing/TestDocumentsProvider.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui.testing;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.os.AsyncTask;
+import android.os.CancellationSignal;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsProvider;
+import android.util.Log;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TestDocumentsProvider extends DocumentsProvider {
+    private static final String TAG = "TestDocumentsProvider";
+
+    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+            Root.COLUMN_ROOT_ID,
+            Root.COLUMN_FLAGS,
+            Root.COLUMN_ICON,
+            Root.COLUMN_TITLE,
+            Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
+    };
+
+    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+            Document.COLUMN_DOCUMENT_ID,
+            Document.COLUMN_MIME_TYPE,
+            Document.COLUMN_DISPLAY_NAME,
+            Document.COLUMN_LAST_MODIFIED,
+            Document.COLUMN_FLAGS,
+            Document.COLUMN_SIZE,
+    };
+
+    private static String[] resolveRootProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
+    }
+
+    private static String[] resolveDocumentProjection(String[] projection) {
+        return projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION;
+    }
+
+    @Override
+    public boolean onCreate() {
+        resetRoots();
+        return true;
+    }
+
+    @Override
+    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
+
+        RowBuilder row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, "local");
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
+        row.add(Root.COLUMN_TITLE, "TEST-Local");
+        row.add(Root.COLUMN_SUMMARY, "TEST-LocalSummary");
+        row.add(Root.COLUMN_DOCUMENT_ID, "doc:local");
+
+        row = result.newRow();
+        row.add(Root.COLUMN_ROOT_ID, "create");
+        row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_IS_CHILD);
+        row.add(Root.COLUMN_TITLE, "TEST-Create");
+        row.add(Root.COLUMN_DOCUMENT_ID, "doc:create");
+
+        return result;
+    }
+
+    private Map<String, Doc> mDocs = new HashMap<>();
+
+    private Doc mLocalRoot;
+    private Doc mCreateRoot;
+
+    private Doc buildDoc(String docId, String displayName, String mimeType) {
+        final Doc doc = new Doc();
+        doc.docId = docId;
+        doc.displayName = displayName;
+        doc.mimeType = mimeType;
+        mDocs.put(doc.docId, doc);
+        return doc;
+    }
+
+    public void resetRoots() {
+        Log.d(TAG, "resetRoots()");
+
+        mDocs.clear();
+
+        mLocalRoot = buildDoc("doc:local", null, Document.MIME_TYPE_DIR);
+
+        mCreateRoot = buildDoc("doc:create", null, Document.MIME_TYPE_DIR);
+        mCreateRoot.flags = Document.FLAG_DIR_SUPPORTS_CREATE;
+
+        {
+            Doc file1 = buildDoc("doc:file1", "FILE1", "mime1/file1");
+            file1.contents = "fileone".getBytes();
+            file1.flags = Document.FLAG_SUPPORTS_WRITE;
+            mLocalRoot.children.add(file1);
+            mCreateRoot.children.add(file1);
+        }
+
+        {
+            Doc file2 = buildDoc("doc:file2", "FILE2", "mime2/file2");
+            file2.contents = "filetwo".getBytes();
+            file2.flags = Document.FLAG_SUPPORTS_WRITE;
+            mLocalRoot.children.add(file2);
+            mCreateRoot.children.add(file2);
+        }
+
+        Doc dir1 = buildDoc("doc:dir1", "DIR1", Document.MIME_TYPE_DIR);
+        mLocalRoot.children.add(dir1);
+
+        {
+            Doc file3 = buildDoc("doc:file3", "FILE3", "mime3/file3");
+            file3.contents = "filethree".getBytes();
+            file3.flags = Document.FLAG_SUPPORTS_WRITE;
+            dir1.children.add(file3);
+        }
+
+        Doc dir2 = buildDoc("doc:dir2", "DIR2", Document.MIME_TYPE_DIR);
+        mCreateRoot.children.add(dir2);
+
+        {
+            Doc file4 = buildDoc("doc:file4", "FILE4", "mime4/file4");
+            file4.contents = "filefour".getBytes();
+            file4.flags = Document.FLAG_SUPPORTS_WRITE;
+            dir2.children.add(file4);
+        }
+    }
+
+    private static class Doc {
+        public String docId;
+        public int flags;
+        public String displayName;
+        public long size;
+        public String mimeType;
+        public long lastModified;
+        public byte[] contents;
+        public List<Doc> children = new ArrayList<>();
+
+        public void include(MatrixCursor result) {
+            final RowBuilder row = result.newRow();
+            row.add(Document.COLUMN_DOCUMENT_ID, docId);
+            row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+            row.add(Document.COLUMN_SIZE, size);
+            row.add(Document.COLUMN_MIME_TYPE, mimeType);
+            row.add(Document.COLUMN_FLAGS, flags);
+            row.add(Document.COLUMN_LAST_MODIFIED, lastModified);
+        }
+    }
+
+    @Override
+    public boolean isChildDocument(String parentDocumentId, String documentId) {
+        for (Doc doc : mDocs.get(parentDocumentId).children) {
+            if (doc.docId.equals(documentId)) {
+                return true;
+            }
+            if (Document.MIME_TYPE_DIR.equals(doc.mimeType)) {
+                return isChildDocument(doc.docId, documentId);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String createDocument(String parentDocumentId, String mimeType, String displayName)
+            throws FileNotFoundException {
+        final String docId = "doc:" + System.currentTimeMillis();
+        final Doc doc = buildDoc(docId, displayName, mimeType);
+        doc.flags = Document.FLAG_SUPPORTS_WRITE | Document.FLAG_SUPPORTS_RENAME;
+        mDocs.get(parentDocumentId).children.add(doc);
+        return docId;
+    }
+
+    @Override
+    public String renameDocument(String documentId, String displayName)
+            throws FileNotFoundException {
+        mDocs.get(documentId).displayName = displayName;
+        return null;
+    }
+
+    @Override
+    public void deleteDocument(String documentId) throws FileNotFoundException {
+        mDocs.remove(documentId);
+        for (Doc doc : mDocs.values()) {
+            doc.children.remove(documentId);
+        }
+    }
+
+    @Override
+    public Cursor queryDocument(String documentId, String[] projection)
+            throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        mDocs.get(documentId).include(result);
+        return result;
+    }
+
+    @Override
+    public Cursor queryChildDocuments(String parentDocumentId, String[] projection,
+            String sortOrder) throws FileNotFoundException {
+        final MatrixCursor result = new MatrixCursor(resolveDocumentProjection(projection));
+        for (Doc doc : mDocs.get(parentDocumentId).children) {
+            doc.include(result);
+        }
+        return result;
+    }
+
+    @Override
+    public ParcelFileDescriptor openDocument(String documentId, String mode,
+            CancellationSignal signal) throws FileNotFoundException {
+        final Doc doc = mDocs.get(documentId);
+        if (doc == null) {
+            throw new FileNotFoundException();
+        }
+        final ParcelFileDescriptor[] pipe;
+        try {
+            pipe = ParcelFileDescriptor.createPipe();
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
+        if (mode.contains("w")) {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    synchronized (doc) {
+                        try {
+                            final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
+                                    pipe[0]);
+                            doc.contents = readFullyNoClose(is);
+                            is.close();
+                            doc.notifyAll();
+                        } catch (IOException e) {
+                            Log.w(TAG, "Failed to stream", e);
+                        }
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
+            return pipe[1];
+        } else {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    synchronized (doc) {
+                        try {
+                            final OutputStream os = new ParcelFileDescriptor.AutoCloseOutputStream(
+                                    pipe[1]);
+                            while (doc.contents == null) {
+                                doc.wait();
+                            }
+                            os.write(doc.contents);
+                            os.close();
+                        } catch (IOException e) {
+                            Log.w(TAG, "Failed to stream", e);
+                        } catch (InterruptedException e) {
+                            Log.w(TAG, "Interuppted", e);
+                        }
+                    }
+                    return null;
+                }
+            }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
+            return pipe[0];
+        }
+    }
+
+    private static byte[] readFullyNoClose(InputStream in) throws IOException {
+        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int count;
+        while ((count = in.read(buffer)) != -1) {
+            bytes.write(buffer, 0, count);
+        }
+        return bytes.toByteArray();
+    }
+}
diff --git a/packages/DocumentsUI/tests/Android.mk b/packages/DocumentsUI/tests/Android.mk
index 3f191a9..cf486b1 100644
--- a/packages/DocumentsUI/tests/Android.mk
+++ b/packages/DocumentsUI/tests/Android.mk
@@ -3,11 +3,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target guava
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target guava ub-uiautomator
 
 LOCAL_PACKAGE_NAME := DocumentsUITests
 LOCAL_INSTRUMENTATION_FOR := DocumentsUI
@@ -15,3 +16,5 @@
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
+
+include $(LOCAL_PATH)/../testing/TestDocumentsProvider/Android.mk
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
new file mode 100644
index 0000000..1f4b751
--- /dev/null
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/FilesActivityUiTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Configurator;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.view.MotionEvent;
+
+import java.util.concurrent.TimeoutException;
+
+public class FilesActivityUiTest extends InstrumentationTestCase {
+
+    private static final String TAG = "FilesActivityUiTest";
+    private static final String TARGET_PKG = "com.android.documentsui";
+    private static final String LAUNCHER_PKG = "com.android.launcher";
+    private static final int ONE_SECOND = 1000;
+    private static final int FIVE_SECONDS = 5 * ONE_SECOND;
+
+    private ActionBar mBar;
+    private UiDevice mDevice;
+    private Context mContext;
+
+    public void setUp() throws TimeoutException {
+        // Initialize UiDevice instance.
+        mDevice = UiDevice.getInstance(getInstrumentation());
+
+        Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
+
+        // Start from the home screen.
+        mDevice.pressHome();
+        mDevice.wait(Until.hasObject(By.pkg(LAUNCHER_PKG).depth(0)), FIVE_SECONDS);
+
+        // Launch app.
+        mContext = getInstrumentation().getContext();
+        Intent intent = mContext.getPackageManager().getLaunchIntentForPackage(TARGET_PKG);
+        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        mContext.startActivity(intent);
+
+        // Wait for the app to appear.
+        mDevice.wait(Until.hasObject(By.pkg(TARGET_PKG).depth(0)), FIVE_SECONDS);
+        mDevice.waitForIdle();
+
+        mBar = new ActionBar();
+    }
+
+    public void testSwitchMode() throws Exception {
+        UiObject2 mode = mBar.gridMode(100);
+        if (mode != null) {
+            mode.click();
+            assertNotNull(mBar.listMode(ONE_SECOND));
+        } else {
+            mBar.listMode(100).click();
+            assertNotNull(mBar.gridMode(ONE_SECOND));
+        }
+    }
+
+    private class ActionBar {
+
+        public UiObject2 gridMode(int timeout) {
+            // Note that we're using By.desc rather than By.res, because of b/25285770
+            BySelector selector = By.desc("Grid view");
+            if (timeout > 0) {
+                mDevice.wait(Until.findObject(selector), timeout);
+            }
+            return mDevice.findObject(selector);
+        }
+
+        public UiObject2 listMode(int timeout) {
+            // Note that we're using By.desc rather than By.res, because of b/25285770
+            BySelector selector = By.desc("List view");
+            if (timeout > 0) {
+                mDevice.wait(Until.findObject(selector), timeout);
+            }
+            return mDevice.findObject(selector);
+        }
+    }
+}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 9b1f103..c44a7960 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -225,4 +225,10 @@
 
     <!-- [CHAR LIMIT=NONE] Label of a running process that represents another user -->
     <string name="running_process_item_user_label">User: <xliff:g id="user_name">%1$s</xliff:g></string>
+
+    <!-- Launch defaults preference summary with some set [CHAR LIMIT=40] -->
+    <string name="launch_defaults_some">Some defaults set</string>
+    <!-- Launch defaults preference summary with none set [CHAR LIMIT=40] -->
+    <string name="launch_defaults_none">No defaults set</string>
+
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
new file mode 100644
index 0000000..344bf62
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/AppUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settingslib.applications;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.hardware.usb.IUsbManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AppUtils {
+    private static final String TAG = "AppUtils";
+
+    public static CharSequence getLaunchByDefaultSummary(ApplicationsState.AppEntry appEntry,
+            IUsbManager usbManager, PackageManager pm, Context context) {
+        String packageName = appEntry.info.packageName;
+        boolean hasPreferred = hasPreferredActivities(pm, packageName)
+                || hasUsbDefaults(usbManager, packageName);
+        int status = pm.getIntentVerificationStatus(packageName, UserHandle.myUserId());
+        // consider a visible current link-handling state to be any explicitly designated behavior
+        boolean hasDomainURLsPreference =
+                status != PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+        return context.getString(hasPreferred || hasDomainURLsPreference
+                ? R.string.launch_defaults_some
+                : R.string.launch_defaults_none);
+    }
+
+    public static boolean hasUsbDefaults(IUsbManager usbManager, String packageName) {
+        try {
+            if (usbManager != null) {
+                return usbManager.hasDefaults(packageName, UserHandle.myUserId());
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "mUsbManager.hasDefaults", e);
+        }
+        return false;
+    }
+
+    public static boolean hasPreferredActivities(PackageManager pm, String packageName) {
+        // Get list of preferred activities
+        List<ComponentName> prefActList = new ArrayList<>();
+        // Intent list cannot be null. so pass empty list
+        List<IntentFilter> intentList = new ArrayList<>();
+        pm.getPreferredActivities(intentList, prefActList, packageName);
+        Log.d(TAG, "Have " + prefActList.size() + " number of activities in preferred list");
+        return prefActList.size() > 0;
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 9781664..cdb6b93 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -39,6 +39,8 @@
             public static final boolean EnableDismissAll = false;
             // Enables the thumbnail alpha on the front-most task
             public static final boolean EnableThumbnailAlphaOnFrontmost = false;
+            // This disables the search bar integration
+            public static final boolean DisableSearchBar = true;
             // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // Enables the simulated task affiliations
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 331a124..c416967 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -206,15 +206,19 @@
                 mEmptyView = mEmptyViewStub.inflate();
             }
             mEmptyView.setVisibility(View.VISIBLE);
-            mRecentsView.setSearchBarVisibility(View.GONE);
+            if (!Constants.DebugFlags.App.DisableSearchBar) {
+                mRecentsView.setSearchBarVisibility(View.GONE);
+            }
         } else {
             if (mEmptyView != null) {
                 mEmptyView.setVisibility(View.GONE);
             }
-            if (mRecentsView.hasValidSearchBar()) {
-                mRecentsView.setSearchBarVisibility(View.VISIBLE);
-            } else {
-                refreshSearchWidgetView();
+            if (!Constants.DebugFlags.App.DisableSearchBar) {
+                if (mRecentsView.hasValidSearchBar()) {
+                    mRecentsView.setSearchBarVisibility(View.VISIBLE);
+                } else {
+                    refreshSearchWidgetView();
+                }
             }
         }
 
@@ -315,7 +319,9 @@
 
         // Initialize the widget host (the host id is static and does not change)
         mConfig = RecentsConfiguration.getInstance();
-        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+        if (!Constants.DebugFlags.App.DisableSearchBar) {
+            mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+        }
         mPackageMonitor = new RecentsPackageMonitor();
         mPackageMonitor.register(this);
 
@@ -330,12 +336,16 @@
         mScrimViews = new SystemBarScrimViews(this);
 
         // Bind the search app widget when we first start up
-        mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
+        if (!Constants.DebugFlags.App.DisableSearchBar) {
+            mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
+        }
 
         // Register the broadcast receiver to handle messages when the screen is turned off
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
-        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        if (!Constants.DebugFlags.App.DisableSearchBar) {
+            filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
+        }
         registerReceiver(mSystemBroadcastReceiver, filter);
     }
 
@@ -420,7 +430,10 @@
         mPackageMonitor.unregister();
 
         // Stop listening for widget package changes if there was one bound
-        mAppWidgetHost.stopListening();
+        if (!Constants.DebugFlags.App.DisableSearchBar) {
+            mAppWidgetHost.stopListening();
+        }
+
         EventBus.getDefault().unregister(this);
     }
 
@@ -551,7 +564,7 @@
                 @Override
                 public void run() {
                     // Start listening for widget package changes if there is one bound
-                    if (mAppWidgetHost != null) {
+                    if (!Constants.DebugFlags.App.DisableSearchBar && mAppWidgetHost != null) {
                         mAppWidgetHost.startListening();
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 563956b..d8f4023 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -165,7 +165,8 @@
         } else {
             // In portrait, the search bar appears on the top (which already has the inset)
             int swInset = getInsetToSmallestWidth(windowBounds.right - windowBounds.left);
-            taskStackBounds.set(windowBounds.left + swInset, searchBarBounds.bottom,
+            int top = searchBarBounds.isEmpty() ? topInset : 0;
+            taskStackBounds.set(windowBounds.left + swInset, searchBarBounds.bottom + top,
                     windowBounds.right - swInset, windowBounds.bottom);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index aaeb10c..07c7897 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -428,7 +428,7 @@
         // Update the configuration for the current state
         mConfig.update(mContext, ssp, ssp.getWindowRect());
 
-        if (tryAndBindSearchWidget) {
+        if (!Constants.DebugFlags.App.DisableSearchBar && tryAndBindSearchWidget) {
             // Try and pre-emptively bind the search widget on startup to ensure that we
             // have the right thumbnail bounds to animate to.
             // Note: We have to reload the widget id before we get the task stack bounds below
@@ -665,7 +665,7 @@
         if (!useThumbnailTransition) {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition and do the animation from home
-            if (hasRecentTasks) {
+            if (!Constants.DebugFlags.App.DisableSearchBar && hasRecentTasks) {
                 String homeActivityPackage = ssp.getHomeActivityPackageName();
                 String searchWidgetPackage = Prefs.getString(mContext,
                         Prefs.Key.SEARCH_APP_WIDGET_PACKAGE, null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 76399f4..cf4c9cb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -34,14 +34,14 @@
  */
 class DockRegion {
     public static TaskStack.DockState[] PHONE_LANDSCAPE = {
-            TaskStack.DockState.LEFT, TaskStack.DockState.RIGHT
+            TaskStack.DockState.LEFT
     };
     public static TaskStack.DockState[] PHONE_PORTRAIT = {
             // We only allow docking to the top for now
             TaskStack.DockState.TOP
     };
     public static TaskStack.DockState[] TABLET_LANDSCAPE = {
-            TaskStack.DockState.LEFT, TaskStack.DockState.RIGHT
+            TaskStack.DockState.LEFT
     };
     public static TaskStack.DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index f156607..a03e7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -141,6 +141,7 @@
     public void onConfigurationChanged() {
         mEndNowButton.setText(mContext.getString(R.string.volume_zen_end_now));
         mSpTexts.update();
+        Util.setText(mEndNowButton, mContext.getString(R.string.volume_zen_end_now));
     }
 
 }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b40ec75..98cfc7c 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -295,10 +295,6 @@
     /** Set when we have taken too long waiting to go to sleep. */
     boolean mSleepTimeout = false;
 
-    /** Indicates if we are running on a Leanback-only (TV) device. Only initialized after
-     * setWindowManager is called. **/
-    private boolean mLeanbackOnlyDevice;
-
     /**
      * We don't want to allow the device to go to sleep while in the process
      * of launching an activity.  This is primarily to allow alarm intent
@@ -446,9 +442,6 @@
             mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
 
             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
-
-            // Initialize this here, now that we can get a valid reference to PackageManager.
-            mLeanbackOnlyDevice = isLeanbackOnlyDevice();
         }
     }
 
@@ -1780,70 +1773,68 @@
     ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, Rect bounds) {
         final TaskRecord task = r.task;
 
-        // On leanback only devices we should keep all activities in the same stack.
-        if (!mLeanbackOnlyDevice &&
-                (r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
+        if (!(r.isApplicationActivity() || (task != null && task.isApplicationTask()))) {
+            return mHomeStack;
+        }
 
-            ActivityStack stack;
+        ActivityStack stack;
 
-            if (task != null && task.stack != null) {
-                stack = task.stack;
-                if (stack.isOnHomeDisplay()) {
-                    if (mFocusedStack != stack) {
-                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                                "computeStackFocus: Setting " + "focused stack to r=" + r
-                                + " task=" + task);
-                    } else {
-                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                            "computeStackFocus: Focused stack already=" + mFocusedStack);
-                    }
-                }
-                return stack;
-            }
-
-            final ActivityContainer container = r.mInitialActivityContainer;
-            if (container != null) {
-                // The first time put it on the desired stack, after this put on task stack.
-                r.mInitialActivityContainer = null;
-                return container.mStack;
-            }
-
-            // The fullscreen stack can contain any task regardless of if the task is resizeable
-            // or not. So, we let the task go in the fullscreen task if it is the focus stack.
-            // If the freeform stack has focus, and the activity to be launched is resizeable,
-            // we can also put it in the focused stack.
-            final boolean canUseFocusedStack =
-                    mFocusedStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID
-                    || mFocusedStack.mStackId == FREEFORM_WORKSPACE_STACK_ID && r.info.resizeable;
-            if (canUseFocusedStack
-                    && (!newTask || mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
-                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                        "computeStackFocus: Have a focused stack=" + mFocusedStack);
-                return mFocusedStack;
-            }
-
-            // We first try to put the task in the first dynamic stack.
-            final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
-            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
-                stack = homeDisplayStacks.get(stackNdx);
-                final boolean isDynamicStack = stack.mStackId >= FIRST_DYNAMIC_STACK_ID;
-                if (isDynamicStack) {
+        if (task != null && task.stack != null) {
+            stack = task.stack;
+            if (stack.isOnHomeDisplay()) {
+                if (mFocusedStack != stack) {
                     if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
-                            "computeStackFocus: Setting focused stack=" + stack);
-                    return stack;
+                            "computeStackFocus: Setting " + "focused stack to r=" + r
+                            + " task=" + task);
+                } else {
+                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
+                        "computeStackFocus: Focused stack already=" + mFocusedStack);
                 }
             }
-
-            // If there is no suitable dynamic stack then we figure out which static stack to use.
-            final int stackId = task != null ? task.getLaunchStackId() :
-                        bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
-                                         FULLSCREEN_WORKSPACE_STACK_ID;
-            stack = getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
-            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
-                    + r + " stackId=" + stack.mStackId);
             return stack;
         }
-        return mHomeStack;
+
+        final ActivityContainer container = r.mInitialActivityContainer;
+        if (container != null) {
+            // The first time put it on the desired stack, after this put on task stack.
+            r.mInitialActivityContainer = null;
+            return container.mStack;
+        }
+
+        // The fullscreen stack can contain any task regardless of if the task is resizeable
+        // or not. So, we let the task go in the fullscreen task if it is the focus stack.
+        // If the freeform stack has focus, and the activity to be launched is resizeable,
+        // we can also put it in the focused stack.
+        final boolean canUseFocusedStack =
+                mFocusedStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID
+                || mFocusedStack.mStackId == FREEFORM_WORKSPACE_STACK_ID && r.info.resizeable;
+        if (canUseFocusedStack
+                && (!newTask || mFocusedStack.mActivityContainer.isEligibleForNewTasks())) {
+            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
+                    "computeStackFocus: Have a focused stack=" + mFocusedStack);
+            return mFocusedStack;
+        }
+
+        // We first try to put the task in the first dynamic stack.
+        final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
+        for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
+            stack = homeDisplayStacks.get(stackNdx);
+            final boolean isDynamicStack = stack.mStackId >= FIRST_DYNAMIC_STACK_ID;
+            if (isDynamicStack) {
+                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
+                        "computeStackFocus: Setting focused stack=" + stack);
+                return stack;
+            }
+        }
+
+        // If there is no suitable dynamic stack then we figure out which static stack to use.
+        final int stackId = task != null ? task.getLaunchStackId() :
+                    bounds != null ? FREEFORM_WORKSPACE_STACK_ID :
+                                     FULLSCREEN_WORKSPACE_STACK_ID;
+        stack = getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
+        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+                + r + " stackId=" + stack.mStackId);
+        return stack;
     }
 
     boolean setFocusedStack(ActivityRecord r, String reason) {
@@ -3198,7 +3189,7 @@
      */
     private boolean restoreRecentTaskLocked(TaskRecord task, int stackId) {
         if (stackId == INVALID_STACK_ID) {
-            stackId = mLeanbackOnlyDevice ? mHomeStack.mStackId : task.getLaunchStackId();
+            stackId = task.getLaunchStackId();
         }
         if (task.stack != null) {
             // Task has already been restored once. See if we need to do anything more
@@ -4950,18 +4941,6 @@
         }
     }
 
-    private boolean isLeanbackOnlyDevice() {
-        boolean onLeanbackOnly = false;
-        try {
-            onLeanbackOnly = AppGlobals.getPackageManager().hasSystemFeature(
-                    PackageManager.FEATURE_LEANBACK_ONLY);
-        } catch (RemoteException e) {
-            // noop
-        }
-
-        return onLeanbackOnly;
-    }
-
     /**
      * Adjust bounds to stay within stack bounds.
      *
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7abc048..2365a45 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -778,11 +778,17 @@
                         int unscaledThumbHeight = (int) (thumbHeight / scale);
                         mTmpFromClipRect.bottom = mTmpFromClipRect.top + unscaledThumbHeight;
                     } else {
-                        // In landscape, we scale the height and clip to the top/left square
-                        scale = thumbHeight / (appHeight - contentInsets.top);
+                        // In landscape, we scale the height and clip to the top/left square. We
+                        // only scale the part that is not covered by status bar and the nav bar.
+                        scale = thumbHeight / (appHeight - contentInsets.top
+                                - contentInsets.bottom);
                         scaledTopDecor = (int) (scale * contentInsets.top);
                         int unscaledThumbWidth = (int) (thumbWidth / scale);
                         mTmpFromClipRect.right = mTmpFromClipRect.left + unscaledThumbWidth;
+                        // This removes the navigation bar from the first frame, so it better
+                        // matches the thumbnail. We need to do this explicitly in landscape,
+                        // because in portrait we already crop vertically.
+                        mTmpFromClipRect.bottom = mTmpFromClipRect.bottom - contentInsets.bottom;
                     }
 
                     mNextAppTransitionInsets.set(contentInsets);
@@ -836,11 +842,16 @@
                     int unscaledThumbHeight = (int) (thumbHeight / scale);
                     mTmpToClipRect.bottom = mTmpToClipRect.top + unscaledThumbHeight;
                 } else {
-                    // In landscape, we scale the height and clip to the top/left square
-                    scale = thumbHeight / (appHeight - contentInsets.top);
+                    // In landscape, we scale the height and clip to the top/left square. We only
+                    // scale the part that is not covered by status bar and the nav bar.
+                    scale = thumbHeight / (appHeight - contentInsets.top - contentInsets.bottom);
                     scaledTopDecor = (int) (scale * contentInsets.top);
                     int unscaledThumbWidth = (int) (thumbWidth / scale);
                     mTmpToClipRect.right = mTmpToClipRect.left + unscaledThumbWidth;
+                    // This removes the navigation bar from the last frame, so it better matches the
+                    // thumbnail. We need to do this explicitly in landscape, because in portrait we
+                    // already crop vertically.
+                    mTmpToClipRect.bottom = mTmpToClipRect.bottom - contentInsets.bottom;
                 }
 
                 mNextAppTransitionInsets.set(contentInsets);