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);