Merge "Removing landscape string overrides" into ub-now-queens
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index fa5fe73..0858d6a 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -15,20 +15,20 @@
-->
<!-- Full screen view projects under the status bar and contains the background -->
-<FrameLayout
+<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg">
+ android:background="@drawable/workspace_bg"
+ android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
android:id="@+id/drag_layer"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:layout_height="match_parent">
<com.android.launcher3.FocusIndicatorView
android:id="@+id/focus_indicator"
@@ -70,4 +70,4 @@
android:layout_height="match_parent"
android:inflatedId="@+id/launcher_overlay"
android:layout="@layout/launcher_overlay" />
-</FrameLayout>
+</com.android.launcher3.LauncherRootView>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index f2d2dd8..7ba7a89 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -15,14 +15,15 @@
-->
<!-- Full screen view projects under the status bar and contains the background -->
-<FrameLayout
+<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg">
+ android:background="@drawable/workspace_bg"
+ android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
android:id="@+id/drag_layer"
@@ -90,4 +91,4 @@
android:layout_height="match_parent"
android:inflatedId="@+id/launcher_overlay"
android:layout="@layout/launcher_overlay" />
-</FrameLayout>
+</com.android.launcher3.LauncherRootView>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 87fa2ed..d4fa2fa 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -15,20 +15,20 @@
-->
<!-- Full screen view projects under the status bar and contains the background -->
-<FrameLayout
+<com.android.launcher3.LauncherRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:id="@+id/launcher"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/workspace_bg">
+ android:background="@drawable/workspace_bg"
+ android:fitsSystemWindows="true">
<com.android.launcher3.DragLayer
android:id="@+id/drag_layer"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
+ android:layout_height="match_parent">
<com.android.launcher3.FocusIndicatorView
android:id="@+id/focus_indicator"
@@ -90,4 +90,4 @@
android:inflatedId="@+id/launcher_overlay"
android:layout="@layout/launcher_overlay" />
-</FrameLayout>
+</com.android.launcher3.LauncherRootView>
diff --git a/res/layout/drop_target_bar.xml b/res/layout/drop_target_bar.xml
deleted file mode 100644
index f38a500..0000000
--- a/res/layout/drop_target_bar.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/DropTargetButtonContainer"
- android:layout_weight="1">
- <!-- Delete target -->
- <com.android.launcher3.DeleteDropTarget
- style="@style/DropTargetButton"
- android:id="@+id/delete_target_text"
- android:text="@string/delete_zone_label_workspace"
- android:drawableStart="@drawable/remove_target_selector" />
- </FrameLayout>
- <FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/DropTargetButtonContainer"
- android:layout_weight="1">
- <!-- Info target -->
- <com.android.launcher3.InfoDropTarget
- style="@style/DropTargetButton"
- android:id="@+id/info_target_text"
- android:text="@string/info_target_label"
- android:drawableStart="@drawable/info_target_selector" />
- </FrameLayout>
-</merge>
diff --git a/res/layout/launcher_overlay.xml b/res/layout/launcher_overlay.xml
index 9ef0c9a..b35a2d8 100644
--- a/res/layout/launcher_overlay.xml
+++ b/res/layout/launcher_overlay.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<FrameLayout
+<com.android.launcher3.InsettableFrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent" />
\ No newline at end of file
+ android:layout_height="match_parent" />
diff --git a/res/layout/launcher_overlay_example.xml b/res/layout/launcher_overlay_example.xml
index 422f281..1556b6f 100644
--- a/res/layout/launcher_overlay_example.xml
+++ b/res/layout/launcher_overlay_example.xml
@@ -16,8 +16,10 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ launcher:layout_ignoreInsets="true">
<FrameLayout
android:id="@+id/search_overlay"
diff --git a/res/layout/search_drop_target_bar.xml b/res/layout/search_drop_target_bar.xml
index 2d51b93..af2d0163 100644
--- a/res/layout/search_drop_target_bar.xml
+++ b/res/layout/search_drop_target_bar.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+ Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,21 +14,45 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.SearchDropTargetBar
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:focusable="false"
+<com.android.launcher3.SearchDropTargetBar xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:focusable="false"
+ android:orientation="horizontal" >
<!-- Drag specific targets container -->
+
<LinearLayout
android:id="@+id/drag_target_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="center">
+ android:layout_gravity="center" >
- <include
- layout="@layout/drop_target_bar" />
+ <FrameLayout
+ style="@style/DropTargetButtonContainer"
+ android:layout_weight="1" >
+
+ <!-- Delete target -->
+
+ <com.android.launcher3.DeleteDropTarget
+ android:id="@+id/delete_target_text"
+ style="@style/DropTargetButton"
+ android:drawableStart="@drawable/remove_target_selector"
+ android:text="@string/delete_zone_label_workspace" />
+ </FrameLayout>
+
+ <FrameLayout
+ style="@style/DropTargetButtonContainer"
+ android:layout_weight="1" >
+
+ <!-- Info target -->
+
+ <com.android.launcher3.InfoDropTarget
+ android:id="@+id/info_target_text"
+ style="@style/DropTargetButton"
+ android:drawableStart="@drawable/info_target_selector"
+ android:text="@string/info_target_label" />
+ </FrameLayout>
</LinearLayout>
-</com.android.launcher3.SearchDropTargetBar>
+
+</com.android.launcher3.SearchDropTargetBar>
\ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 8aa65a4..5d01f36 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Program is nie geïnstalleer nie."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Program is nie beskikbaar nie"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Afgelaaide program in veiligmodus gedeaktiveer"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Legstukke gedeaktiveer in Veiligmodus"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Legstukke"</string>
<string name="widget_adder" msgid="3201040140710381657">"Legstukke"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Wys Mem"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 4b05436..95125bc 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikace není nainstalována."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikace není k dispozici."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Stažená aplikace je v nouzovém režimu zakázána"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"V Bezpečném režimu jsou widgety zakázány."</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgety"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgety"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobrazit Mem"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index d5352f2..c3bb088 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installeret."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgængelig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloadet app er deaktiveret i sikker tilstand"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets er deaktiveret i Beskyttet tilstand"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis Mem"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index dc43f2d..847faac 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"No se instaló la aplicación."</string>
<string name="activity_not_available" msgid="7456344436509528827">"La aplicación no está disponible."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicación descargada inhabilitada en modo seguro"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets inhabilitados en modo seguro"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memoria"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index c765d8f..ce10c2d 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"برنامه نصب نشده است."</string>
<string name="activity_not_available" msgid="7456344436509528827">"برنامه در دسترس نیست"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"برنامه دانلود شده در حالت ایمن غیرفعال شد"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"ابزارکها در حالت ایمن غیرفعال هستند"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"ابزارکها"</string>
<string name="widget_adder" msgid="3201040140710381657">"ابزارکها"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"نمایش Mem"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index c1070f2..a94f571 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets désactivés en mode sans échec"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 064d751..0f1aac4 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"L\'application n\'est pas installée."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Application indisponible"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'application téléchargée est désactivée en mode sécurisé."</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Les widgets sont désactivés en mode sécurisé."</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Afficher la mémoire"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 9402a42..dcff15c 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Ծրագիրը տեղադրված չէ:"</string>
<string name="activity_not_available" msgid="7456344436509528827">"Հավելվածը հասանելի չէ"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ներբեռնված ծրագիրն անջատված է Անվտանգ ռեժիմում"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Վիջեթներն անջատված են անվտանգ ռեժիմում"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Վիջեթներ"</string>
<string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 8092331..823d36a 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"აპი არ არის დაყენებული."</string>
<string name="activity_not_available" msgid="7456344436509528827">"აპი მიუწვდომელია"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"უსაფრთხო რეჟიმში ჩამოტვირთული აპი გაუქმებულია"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"უსაფრთხო რეჟიმში ვიჯეტი გამორთულია"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"ვიჯეტები"</string>
<string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index ac210d7..8a255c9 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -18,27 +18,25 @@
-->
<resources>
-<!-- Search Bar -->
- <style name="SearchButton">
- </style>
+
+ <!-- Search Bar -->
+ <style name="SearchButton"></style>
+
<style name="DropTargetButtonContainer">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
</style>
- <style name="DropTargetButton">
- <item name="android:layout_width">wrap_content</item>
+
+ <!-- This style applies to the drop target when it is shown in the sidebar -->
+ <style name="DropTargetButton" parent="DropTargetButton.Base">
<item name="android:layout_height">wrap_content</item>
- <item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
+ <item name="android:drawablePadding">0dp</item>
<item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
<item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
<item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
<item name="android:paddingRight">@dimen/toolbar_button_horizontal_padding</item>
<item name="android:shadowColor">#DD000000</item>
- <item name="android:shadowDx">0.0</item>
- <item name="android:shadowDy">1.0</item>
- <item name="android:shadowRadius">4.0</item>
</style>
-</resources>
-
+</resources>
\ No newline at end of file
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 935e997..ac47503 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ."</string>
<string name="activity_not_available" msgid="7456344436509528827">"ແອັບຯໃຊ້ບໍ່ໄດ້"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"ແອັບຯທີ່ດາວໂຫລດແລ້ວຖືກປິດການນຳໃຊ້ໃນ Safe mode"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"ວິດເຈັດຖືກປິດໃນ Safe mode"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"ວິດເຈັດ"</string>
<string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 1770e89..5f96ead 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Apl tidak dipasang."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Apl tidak tersedia"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Apl yang dimuat turun dilumpuhkan dalam mod Selamat"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widget dilumpuhkan dalam mod Selamat"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widget"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widget"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Papar Mem"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 6211361..a7faeaf 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Appen er ikke installert."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen er ikke tilgjengelig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"En nedlastet app er deaktivert i sikker modus"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Moduler er deaktivert i sikker modus"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Moduler"</string>
<string name="widget_adder" msgid="3201040140710381657">"Moduler"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Vis minne"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 355e71a..6c9a0d9 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"O app não está instalado."</string>
<string name="activity_not_available" msgid="7456344436509528827">"O app não está disponível"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"App transferido por download desativado no modo de segurança"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets desativados no modo de segurança"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgets"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgets"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mostrar memória"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 7cbd9fa..8b9d706 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Приложение удалено"</string>
<string name="activity_not_available" msgid="7456344436509528827">"Приложение недоступно"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Скачанное приложение отключено в безопасном режиме"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Виджеты отключены в безопасном режиме"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Виджеты"</string>
<string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index e3c242d..2ffa4b4 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikácia nie je nainštalovaná."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikácia nie je k dispozícii"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Stiahnutá aplikácia je v núdzovom režime zakázaná"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Miniaplikácie sú v núdzovom režime zakázané"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Miniaplikácie"</string>
<string name="widget_adder" msgid="3201040140710381657">"Miniaplikácie"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Zobraziť pamäť"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 807b1b4..f02ea27 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija ni nameščena."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija ni na voljo"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Prenesena aplikacija je onemogočena v Varnem načinu"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Pripomočki so onemogočeni v varnem načinu"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Pripomočki"</string>
<string name="widget_adder" msgid="3201040140710381657">"Pripomočki"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaži pomnilnik"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 0284679..05df3c4 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Programu haijasakinishwa."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Programu haipatikani"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Programu iliyopakuliwa imezimwa katika Hali Salama"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Wijeti zimezimwa katika hali ya Usalama"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Wijeti"</string>
<string name="widget_adder" msgid="3201040140710381657">"Wijeti"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Onyesha Kumbukumbu"</string>
diff --git a/res/values-sw340dp/dimens.xml b/res/values-sw340dp/dimens.xml
index 69d6e58..c9f2981 100644
--- a/res/values-sw340dp/dimens.xml
+++ b/res/values-sw340dp/dimens.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!--
+ Copyright (C) 2011 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -15,6 +16,9 @@
-->
<resources>
+
<!-- Drag padding to add to the bottom of drop targets -->
<dimen name="drop_target_drag_padding">20dp</dimen>
-</resources>
+ <dimen name="drop_target_text_size">16sp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index 4ec04d9..cbc1e29 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -18,26 +18,22 @@
-->
<resources>
-<!-- Workspace -->
- <style name="SearchButton">
- </style>
+
+ <!-- Workspace -->
+ <style name="SearchButton"></style>
+
<style name="DropTargetButtonContainer">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
</style>
- <style name="DropTargetButton">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">match_parent</item>
- <item name="android:layout_gravity">center</item>
- <item name="android:gravity">center_vertical</item>
- <item name="android:drawablePadding">7.5dp</item>
+
+ <style name="DropTargetButton" parent="DropTargetButton.Base">
<item name="android:paddingLeft">60dp</item>
<item name="android:paddingRight">60dp</item>
- <item name="android:textColor">#FFFFFFFF</item>
- <item name="android:textSize">16sp</item>
<item name="android:shadowColor">#393939</item>
<item name="android:shadowDx">0.0</item>
<item name="android:shadowDy">0.0</item>
<item name="android:shadowRadius">2.0</item>
</style>
-</resources>
+
+</resources>
\ No newline at end of file
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index b71748e..341def7 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"Uygulama yüklü değil."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Uygulama kullanılamıyor"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"İndirilen uygulama Güvenli modda devre dışı bırakıldı"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Güvenli modda widget\'lar devre dışı"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widget\'lar"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widget\'lar"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Belleği Göster"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 30e34b9..e716fde 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,8 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"未安装该应用。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"应用不可用"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"安全模式下不允许使用下载的此应用"</string>
- <!-- no translation found for safemode_widget_error (4863470563535682004) -->
- <skip />
+ <string name="safemode_widget_error" msgid="4863470563535682004">"安全模式下不允许使用小部件"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"小部件"</string>
<string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 3656e2e..02c90f2 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -26,7 +26,7 @@
<string name="activity_not_found" msgid="8071924732094499514">"尚未安裝應用程式。"</string>
<string name="activity_not_available" msgid="7456344436509528827">"目前無法使用這個應用程式"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"在安全模式中無法使用「已下載的應用程式」功能"</string>
- <string name="safemode_widget_error" msgid="4863470563535682004">"在安全模式下無法使用小工具"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"在安全模式中無法使用小工具"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
<string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index b4e1543..a52bbe2 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -145,4 +145,8 @@
<attr name="ringOutset" format="dimension" />
<attr name="indicatorSize" format="dimension" />
</declare-styleable>
+
+ <declare-styleable name="InsettableFrameLayout_Layout">
+ <attr name="layout_ignoreInsets" format="boolean" />
+ </declare-styleable>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2c9e689..20bc7cc 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -62,6 +62,7 @@
<!-- Drag padding to add to the bottom of drop targets -->
<dimen name="drop_target_drag_padding">14dp</dimen>
+ <dimen name="drop_target_text_size">14sp</dimen>
<!-- Dragging -->
<!-- the area at the edge of the screen that makes the workspace go left
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a6397e3..b3abe8f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -125,11 +125,11 @@
device. [CHAR_LIMIT=30]-->
<string name="delete_zone_label_all_apps">Uninstall</string>
- <!-- Label for delete drop target. [CHAR_LIMIT=30] -->
+ <!-- Label for delete drop target. [CHAR_LIMIT=20] -->
<string name="delete_target_label">Remove</string>
- <!-- Label for uninstall drop target. [CHAR_LIMIT=30]-->
+ <!-- Label for uninstall drop target. [CHAR_LIMIT=20]-->
<string name="delete_target_uninstall_label">Uninstall</string>
- <!-- Label for the info icon. [CHAR_LIMIT=30] -->
+ <!-- Label for the info icon. [CHAR_LIMIT=20] -->
<string name="info_target_label">App info</string>
<!-- Accessibility: Search button -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 873b74c..15415c7 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,10 +32,9 @@
<item name="android:fontFamily">sans-serif-condensed</item>
</style>
- <style name="WorkspaceIcon.Portrait">
- </style>
- <style name="WorkspaceIcon.Landscape">
- </style>
+ <style name="WorkspaceIcon.Portrait"></style>
+
+ <style name="WorkspaceIcon.Landscape"></style>
<style name="WorkspaceIcon.AppsCustomize">
<item name="android:background">@null</item>
@@ -52,15 +51,16 @@
<item name="customShadows">false</item>
</style>
- <style name="SearchDropTargetBar">
- </style>
- <style name="SearchButton">
- </style>
+ <style name="SearchDropTargetBar"></style>
+
+ <style name="SearchButton"></style>
+
<style name="DropTargetButtonContainer">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
</style>
- <style name="DropTargetButton">
+
+ <style name="DropTargetButton.Base">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center</item>
@@ -69,7 +69,7 @@
<item name="android:paddingLeft">25dp</item>
<item name="android:paddingRight">25dp</item>
<item name="android:textColor">#FFFFFFFF</item>
- <item name="android:textSize">16sp</item>
+ <item name="android:textSize">@dimen/drop_target_text_size</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
<item name="android:shadowColor">#FF000000</item>
@@ -78,6 +78,8 @@
<item name="android:shadowRadius">4.0</item>
</style>
+ <style name="DropTargetButton" parent="DropTargetButton.Base"></style>
+
<style name="PreloadIcon">
<item name="background">@drawable/virtual_preload</item>
<item name="indicatorSize">4dp</item>
@@ -94,7 +96,9 @@
<style name="PagedViewWidgetImageView">
<item name="android:paddingLeft">@dimen/app_widget_preview_padding_left</item>
</style>
+
<style name="SearchButton.WithPaddingStart">
<item name="android:paddingLeft">8dp</item>
</style>
+
</resources>
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index ff9072a..79d4278 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -43,7 +43,7 @@
/**
* A ViewGroup that coordinates dragging across its descendants
*/
-public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChangeListener {
+public class DragLayer extends InsettableFrameLayout {
private DragController mDragController;
private int[] mTmpXY = new int[2];
@@ -71,8 +71,6 @@
private TouchCompleteListener mTouchCompleteListener;
- private final Rect mInsets = new Rect();
-
private View mOverlayView;
private int mTopViewIndex;
private int mChildCountOnLastUpdate = -1;
@@ -103,7 +101,6 @@
// Disable multitouch across the workspace/all apps/customize tray
setMotionEventSplittingEnabled(false);
setChildrenDrawingOrderEnabled(true);
- setOnHierarchyChangeListener(this);
final Resources res = getResources();
mLeftHoverDrawable = res.getDrawable(R.drawable.page_hover_left);
@@ -123,27 +120,6 @@
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- final int n = getChildCount();
- for (int i = 0; i < n; i++) {
- final View child = getChildAt(i);
- setInsets(child, insets, mInsets);
- }
- mInsets.set(insets);
- return true; // I'll take it from here
- }
-
- Rect getInsets() {
- return mInsets;
- }
-
- @Override
- public void addView(View child, int index, android.view.ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
- setInsets(child, mInsets, new Rect());
- }
-
public void showOverlayView(View overlayView) {
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mOverlayView = overlayView;
@@ -158,19 +134,6 @@
removeView(mOverlayView);
}
- private void setInsets(View child, Rect newInsets, Rect oldInsets) {
- final FrameLayout.LayoutParams flp = (FrameLayout.LayoutParams) child.getLayoutParams();
- if (child instanceof Insettable) {
- ((Insettable) child).setInsets(newInsets);
- } else {
- flp.topMargin += (newInsets.top - oldInsets.top);
- flp.leftMargin += (newInsets.left - oldInsets.left);
- flp.rightMargin += (newInsets.right - oldInsets.right);
- flp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
- }
- child.setLayoutParams(flp);
- }
-
private boolean isEventOverFolderTextRegion(Folder folder, MotionEvent ev) {
getDescendantRectRelativeToSelf(folder.getEditTextRegion(), mHitRect);
if (mHitRect.contains((int) ev.getX(), (int) ev.getY())) {
@@ -815,6 +778,7 @@
@Override
public void onChildViewAdded(View parent, View child) {
+ super.onChildViewAdded(parent, child);
if (mOverlayView != null) {
// ensure that the overlay view stays on top. we can't use drawing order for this
// because in API level 16 touch dispatch doesn't respect drawing order.
diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java
new file mode 100644
index 0000000..1c3d5a1
--- /dev/null
+++ b/src/com/android/launcher3/InsettableFrameLayout.java
@@ -0,0 +1,96 @@
+package com.android.launcher3;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+public class InsettableFrameLayout extends FrameLayout implements
+ ViewGroup.OnHierarchyChangeListener, Insettable {
+
+ protected Rect mInsets = new Rect();
+
+ public InsettableFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOnHierarchyChangeListener(this);
+ }
+
+ public void setFrameLayoutChildInsets(View child, Rect newInsets, Rect oldInsets) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ if (child instanceof Insettable) {
+ ((Insettable) child).setInsets(newInsets);
+ } else if (!lp.ignoreInsets) {
+ lp.topMargin += (newInsets.top - oldInsets.top);
+ lp.leftMargin += (newInsets.left - oldInsets.left);
+ lp.rightMargin += (newInsets.right - oldInsets.right);
+ lp.bottomMargin += (newInsets.bottom - oldInsets.bottom);
+ }
+ child.setLayoutParams(lp);
+ }
+
+ @Override
+ public void setInsets(Rect insets) {
+ final int n = getChildCount();
+ for (int i = 0; i < n; i++) {
+ final View child = getChildAt(i);
+ setFrameLayoutChildInsets(child, insets, mInsets);
+ }
+ mInsets.set(insets);
+ }
+
+ @Override
+ public LayoutParams generateLayoutParams(AttributeSet attrs) {
+ return new InsettableFrameLayout.LayoutParams(getContext(), attrs);
+ }
+
+ @Override
+ protected LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ }
+
+ // Override to allow type-checking of LayoutParams.
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ return p instanceof InsettableFrameLayout.LayoutParams;
+ }
+
+ @Override
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
+ return new LayoutParams(p);
+ }
+
+ class LayoutParams extends FrameLayout.LayoutParams {
+ boolean ignoreInsets = false;
+
+ public LayoutParams(Context c, AttributeSet attrs) {
+ super(c, attrs);
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ R.styleable.InsettableFrameLayout_Layout);
+ ignoreInsets = a.getBoolean(
+ R.styleable.InsettableFrameLayout_Layout_layout_ignoreInsets, false);
+ a.recycle();
+ }
+
+ public LayoutParams(int width, int height) {
+ super(width, height);
+ }
+
+ public LayoutParams(ViewGroup.LayoutParams lp) {
+ super(lp);
+ }
+ }
+
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ setFrameLayoutChildInsets(child, mInsets, new Rect());
+ }
+
+ @Override
+ public void onChildViewRemoved(View parent, View child) {
+ }
+
+}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 309837f..b357e7a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -231,7 +231,7 @@
LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl();
LauncherOverlay mLauncherOverlay;
- ViewGroup mLauncherOverlayView;
+ InsettableFrameLayout mLauncherOverlayContainer;
static final int APPWIDGET_HOST_ID = 1024;
public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
@@ -514,9 +514,9 @@
mLauncherCallbacks.onCreate(savedInstanceState);
if (mLauncherCallbacks.hasLauncherOverlay()) {
ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub);
- mLauncherOverlayView = (ViewGroup) stub.inflate();
- mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(mLauncherOverlayView,
- mLauncherOverlayCallbacks);
+ mLauncherOverlayContainer = (InsettableFrameLayout) stub.inflate();
+ mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(
+ mLauncherOverlayContainer, mLauncherOverlayCallbacks);
mWorkspace.setLauncherOverlay(mLauncherOverlay);
}
}
@@ -3741,14 +3741,14 @@
yDrift = isWidgetTray ? height / 2 : allAppsToPanelDelta[1];
xDrift = isWidgetTray ? 0 : allAppsToPanelDelta[0];
} else {
- yDrift = 5 * height / 4;
+ yDrift = 2 * height / 3;
xDrift = 0;
}
revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
TimeInterpolator decelerateInterpolator = material ?
new LogDecelerateInterpolator(100, 0) :
- new LogDecelerateInterpolator(30, 0);
+ new DecelerateInterpolator(1f);
// The vertical motion of the apps panel should be delayed by one frame
// from the conceal animation in order to give the right feel. We correpsondingly
@@ -3772,9 +3772,9 @@
revealView.setAlpha(1f);
ObjectAnimator panelAlpha = LauncherAnimUtils.ofFloat(revealView, "alpha",
1f, finalAlpha);
- panelAlpha.setDuration(revealDuration);
- panelAlpha.setInterpolator(material ? decelerateInterpolator :
- new AccelerateInterpolator(1.5f));
+ panelAlpha.setDuration(material ? revealDuration : 150);
+ panelAlpha.setInterpolator(decelerateInterpolator);
+ panelAlpha.setStartDelay(material ? 0 : itemsAlphaStagger + SINGLE_FRAME_DELAY);
mStateAnimation.play(panelAlpha);
}
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index c20c693..09ad22b 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -78,6 +78,12 @@
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
throws IOException {
+ if (!Utilities.isLmpOrAbove()) {
+ // No restore for old devices.
+ Log.i(TAG, "You shall not pass!!!");
+ Log.d(TAG, "Restore is only supported on devices running Lollipop and above.");
+ return;
+ }
super.onRestore(data, appVersionCode, newState);
// If no favorite was migrated, clear the data and start fresh.
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 201f3e9..b2ac577 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -15,22 +15,6 @@
*/
package com.android.launcher3;
-import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
-import com.google.protobuf.nano.MessageNano;
-
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.LauncherSettings.WorkspaceScreens;
-import com.android.launcher3.backup.BackupProtos;
-import com.android.launcher3.backup.BackupProtos.CheckedMessage;
-import com.android.launcher3.backup.BackupProtos.Favorite;
-import com.android.launcher3.backup.BackupProtos.Journal;
-import com.android.launcher3.backup.BackupProtos.Key;
-import com.android.launcher3.backup.BackupProtos.Resource;
-import com.android.launcher3.backup.BackupProtos.Screen;
-import com.android.launcher3.backup.BackupProtos.Widget;
-import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.compat.UserHandleCompat;
-
import android.app.backup.BackupDataInputStream;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupHelper;
@@ -42,6 +26,7 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -51,6 +36,21 @@
import android.util.Base64;
import android.util.Log;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.WorkspaceScreens;
+import com.android.launcher3.backup.BackupProtos;
+import com.android.launcher3.backup.BackupProtos.CheckedMessage;
+import com.android.launcher3.backup.BackupProtos.Favorite;
+import com.android.launcher3.backup.BackupProtos.Journal;
+import com.android.launcher3.backup.BackupProtos.Key;
+import com.android.launcher3.backup.BackupProtos.Resource;
+import com.android.launcher3.backup.BackupProtos.Screen;
+import com.android.launcher3.backup.BackupProtos.Widget;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+import com.google.protobuf.nano.MessageNano;
+
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -60,7 +60,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.zip.CRC32;
/**
@@ -71,7 +70,6 @@
private static final String TAG = "LauncherBackupHelper";
private static final boolean VERBOSE = LauncherBackupAgentHelper.VERBOSE;
private static final boolean DEBUG = LauncherBackupAgentHelper.DEBUG;
- private static final boolean DEBUG_PAYLOAD = false;
private static final int MAX_JOURNAL_SIZE = 1000000;
@@ -90,27 +88,25 @@
private static final Bitmap.CompressFormat IMAGE_FORMAT =
android.graphics.Bitmap.CompressFormat.PNG;
- private static BackupManager sBackupManager;
-
private static final String[] FAVORITE_PROJECTION = {
- Favorites._ID, // 0
- Favorites.MODIFIED, // 1
- Favorites.INTENT, // 2
- Favorites.APPWIDGET_PROVIDER, // 3
- Favorites.APPWIDGET_ID, // 4
- Favorites.CELLX, // 5
- Favorites.CELLY, // 6
- Favorites.CONTAINER, // 7
- Favorites.ICON, // 8
- Favorites.ICON_PACKAGE, // 9
- Favorites.ICON_RESOURCE, // 10
- Favorites.ICON_TYPE, // 11
- Favorites.ITEM_TYPE, // 12
- Favorites.SCREEN, // 13
- Favorites.SPANX, // 14
- Favorites.SPANY, // 15
- Favorites.TITLE, // 16
- Favorites.PROFILE_ID, // 17
+ Favorites._ID, // 0
+ Favorites.MODIFIED, // 1
+ Favorites.INTENT, // 2
+ Favorites.APPWIDGET_PROVIDER, // 3
+ Favorites.APPWIDGET_ID, // 4
+ Favorites.CELLX, // 5
+ Favorites.CELLY, // 6
+ Favorites.CONTAINER, // 7
+ Favorites.ICON, // 8
+ Favorites.ICON_PACKAGE, // 9
+ Favorites.ICON_RESOURCE, // 10
+ Favorites.ICON_TYPE, // 11
+ Favorites.ITEM_TYPE, // 12
+ Favorites.SCREEN, // 13
+ Favorites.SPANX, // 14
+ Favorites.SPANY, // 15
+ Favorites.TITLE, // 16
+ Favorites.PROFILE_ID, // 17
};
private static final int ID_INDEX = 0;
@@ -130,37 +126,46 @@
private static final int SPANX_INDEX = 14;
private static final int SPANY_INDEX = 15;
private static final int TITLE_INDEX = 16;
- private static final int PROFILE_ID_INDEX = 17;
private static final String[] SCREEN_PROJECTION = {
- WorkspaceScreens._ID, // 0
- WorkspaceScreens.MODIFIED, // 1
- WorkspaceScreens.SCREEN_RANK // 2
+ WorkspaceScreens._ID, // 0
+ WorkspaceScreens.MODIFIED, // 1
+ WorkspaceScreens.SCREEN_RANK // 2
};
private static final int SCREEN_RANK_INDEX = 2;
- private static IconCache mIconCache;
-
private final Context mContext;
-
- private final boolean mRestoreEnabled;
-
- private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap;
-
+ private final HashSet<String> mExistingKeys;
private final ArrayList<Key> mKeys;
+ private IconCache mIconCache;
+ private BackupManager mBackupManager;
+ private HashMap<ComponentName, AppWidgetProviderInfo> mWidgetMap;
+ private byte[] mBuffer = new byte[512];
+ private long mLastBackupRestoreTime;
+
public LauncherBackupHelper(Context context, boolean restoreEnabled) {
mContext = context;
- mRestoreEnabled = restoreEnabled;
+ mExistingKeys = new HashSet<String>();
mKeys = new ArrayList<Key>();
}
private void dataChanged() {
- if (sBackupManager == null) {
- sBackupManager = new BackupManager(mContext);
+ if (mBackupManager == null) {
+ mBackupManager = new BackupManager(mContext);
}
- sBackupManager.dataChanged();
+ mBackupManager.dataChanged();
+ }
+
+ private void applyJournal(Journal journal) {
+ mLastBackupRestoreTime = journal.t;
+ mExistingKeys.clear();
+ if (journal.key != null) {
+ for (Key key : journal.key) {
+ mExistingKeys.add(keyToBackupKey(key));
+ }
+ }
}
/**
@@ -181,32 +186,45 @@
if (VERBOSE) Log.v(TAG, "onBackup");
Journal in = readJournal(oldState);
- Journal out = new Journal();
+ if (!launcherIsReady()) {
+ // Perform backup later.
+ writeJournal(newState, in);
+ return;
+ }
+ Log.v(TAG, "lastBackupTime = " + in.t);
+ mKeys.clear();
+ applyJournal(in);
- long lastBackupTime = in.t;
- out.t = System.currentTimeMillis();
- out.rows = 0;
- out.bytes = 0;
+ // Record the time before performing backup so that entries edited while the backup
+ // was going on, do not get missed in next backup.
+ long newBackupTime = System.currentTimeMillis();
- Log.v(TAG, "lastBackupTime = " + lastBackupTime);
+ try {
+ backupFavorites(data);
+ backupScreens(data);
+ backupIcons(data);
+ backupWidgets(data);
- ArrayList<Key> keys = new ArrayList<Key>();
- if (launcherIsReady()) {
- try {
- backupFavorites(in, data, out, keys);
- backupScreens(in, data, out, keys);
- backupIcons(in, data, out, keys);
- backupWidgets(in, data, out, keys);
- } catch (IOException e) {
- Log.e(TAG, "launcher backup has failed", e);
+ // Delete any key which still exist in the old backup, but is not valid anymore.
+ HashSet<String> validKeys = new HashSet<String>();
+ for (Key key : mKeys) {
+ validKeys.add(keyToBackupKey(key));
}
- out.key = keys.toArray(new BackupProtos.Key[keys.size()]);
- } else {
- out = in;
+ mExistingKeys.removeAll(validKeys);
+
+ // Delete anything left in the existing keys.
+ for (String deleted: mExistingKeys) {
+ if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
+ data.writeEntityHeader(deleted, -1);
+ }
+
+ mExistingKeys.clear();
+ mLastBackupRestoreTime = newBackupTime;
+ } catch (IOException e) {
+ Log.e(TAG, "launcher backup has failed", e);
}
- writeJournal(newState, out);
- Log.v(TAG, "onBackup: wrote " + out.bytes + "b in " + out.rows + " rows.");
+ writeNewStateDescription(newState);
}
/**
@@ -218,49 +236,41 @@
*/
@Override
public void restoreEntity(BackupDataInputStream data) {
- if (VERBOSE) Log.v(TAG, "restoreEntity");
- byte[] buffer = new byte[512];
- String backupKey = data.getKey();
- int dataSize = data.size();
- if (buffer.length < dataSize) {
- buffer = new byte[dataSize];
- }
- Key key = null;
- int bytesRead = 0;
- try {
- bytesRead = data.read(buffer, 0, dataSize);
- if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available");
- } catch (IOException e) {
- Log.e(TAG, "failed to read entity from restore data", e);
+ int dataSize = data.size();
+ if (mBuffer.length < dataSize) {
+ mBuffer = new byte[dataSize];
}
try {
- key = backupKeyToKey(backupKey);
+ int bytesRead = data.read(mBuffer, 0, dataSize);
+ if (DEBUG) Log.d(TAG, "read " + bytesRead + " of " + dataSize + " available");
+ String backupKey = data.getKey();
+ Key key = backupKeyToKey(backupKey);
mKeys.add(key);
switch (key.type) {
case Key.FAVORITE:
- restoreFavorite(key, buffer, dataSize, mKeys);
+ restoreFavorite(key, mBuffer, dataSize);
break;
case Key.SCREEN:
- restoreScreen(key, buffer, dataSize, mKeys);
+ restoreScreen(key, mBuffer, dataSize);
break;
case Key.ICON:
- restoreIcon(key, buffer, dataSize, mKeys);
+ restoreIcon(key, mBuffer, dataSize);
break;
case Key.WIDGET:
- restoreWidget(key, buffer, dataSize, mKeys);
+ restoreWidget(key, mBuffer, dataSize);
break;
default:
Log.w(TAG, "unknown restore entity type: " + key.type);
+ mKeys.remove(key);
break;
}
- } catch (KeyParsingException e) {
- Log.w(TAG, "ignoring unparsable backup key: " + backupKey);
+ } catch (IOException e) {
+ Log.w(TAG, "ignoring unparsable backup entry", e);
}
-
}
/**
@@ -270,63 +280,55 @@
*/
@Override
public void writeNewStateDescription(ParcelFileDescriptor newState) {
- // clear the output journal time, to force a full backup to
- // will catch any changes the restore process might have made
- Journal out = new Journal();
- out.t = 0;
- out.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
- writeJournal(newState, out);
- Log.v(TAG, "onRestore: read " + mKeys.size() + " rows");
- mKeys.clear();
+ writeJournal(newState, getCurrentStateJournal());
+ }
+
+ private Journal getCurrentStateJournal() {
+ Journal journal = new Journal();
+ journal.t = mLastBackupRestoreTime;
+ journal.key = mKeys.toArray(new BackupProtos.Key[mKeys.size()]);
+ journal.appVersion = getAppVersion();
+ return journal;
+ }
+
+ private int getAppVersion() {
+ try {
+ return mContext.getPackageManager()
+ .getPackageInfo(mContext.getPackageName(), 0).versionCode;
+ } catch (NameNotFoundException e) {
+ return 0;
+ }
}
/**
* Write all modified favorites to the data stream.
*
- *
- * @param in notes from last backup
* @param data output stream for key/value pairs
- * @param out notes about this backup
- * @param keys keys to mark as clean in the notes for next backup
* @throws IOException
*/
- private void backupFavorites(Journal in, BackupDataOutput data, Journal out,
- ArrayList<Key> keys)
- throws IOException {
- // read the old ID set
- Set<String> savedIds = getSavedIdsByType(Key.FAVORITE, in);
- if (DEBUG) Log.d(TAG, "favorite savedIds.size()=" + savedIds.size());
-
+ private void backupFavorites(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
// Don't backup apps in other profiles for now.
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
getUserSelectionArg(), null, null);
- Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.FAVORITE, id);
- keys.add(key);
+ mKeys.add(key);
final String backupKey = keyToBackupKey(key);
- currentIds.add(backupKey);
- if (!savedIds.contains(backupKey) || updateTime >= in.t) {
- byte[] blob = packFavorite(cursor);
- writeRowToBackup(key, blob, out, data);
+ if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime) {
+ writeRowToBackup(key, packFavorite(cursor), data);
} else {
- if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
+ if (DEBUG) Log.d(TAG, "favorite already backup up: " + id);
}
}
} finally {
cursor.close();
}
- if (DEBUG) Log.d(TAG, "favorite currentIds.size()=" + currentIds.size());
-
- // these IDs must have been deleted
- savedIds.removeAll(currentIds);
- out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
/**
@@ -337,74 +339,46 @@
* @param key identifier for the row
* @param buffer the serialized proto from the stream, may be larger than dataSize
* @param dataSize the size of the proto from the stream
- * @param keys keys to mark as clean in the notes for next backup
*/
- private void restoreFavorite(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
+ private void restoreFavorite(Key key, byte[] buffer, int dataSize) throws IOException {
if (VERBOSE) Log.v(TAG, "unpacking favorite " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
- if (!mRestoreEnabled) {
- if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
- return;
- }
-
- try {
- ContentResolver cr = mContext.getContentResolver();
- ContentValues values = unpackFavorite(buffer, 0, dataSize);
- cr.insert(Favorites.CONTENT_URI_NO_NOTIFICATION, values);
- } catch (InvalidProtocolBufferNanoException e) {
- Log.e(TAG, "failed to decode favorite", e);
- }
+ ContentResolver cr = mContext.getContentResolver();
+ ContentValues values = unpackFavorite(buffer, dataSize);
+ cr.insert(Favorites.CONTENT_URI_NO_NOTIFICATION, values);
}
/**
* Write all modified screens to the data stream.
*
- *
- * @param in notes from last backup
* @param data output stream for key/value pairs
- * @param out notes about this backup
- * @param keys keys to mark as clean in the notes for next backup
* @throws IOException
*/
- private void backupScreens(Journal in, BackupDataOutput data, Journal out,
- ArrayList<Key> keys)
- throws IOException {
- // read the old ID set
- Set<String> savedIds = getSavedIdsByType(Key.SCREEN, in);
- if (DEBUG) Log.d(TAG, "screen savedIds.size()=" + savedIds.size());
-
+ private void backupScreens(BackupDataOutput data) throws IOException {
// persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(WorkspaceScreens.CONTENT_URI, SCREEN_PROJECTION,
null, null, null);
- Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
- if (DEBUG) Log.d(TAG, "dumping screens after: " + in.t);
+ if (DEBUG) Log.d(TAG, "dumping screens after: " + mLastBackupRestoreTime);
while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX);
final long updateTime = cursor.getLong(ID_MODIFIED);
Key key = getKey(Key.SCREEN, id);
- keys.add(key);
+ mKeys.add(key);
final String backupKey = keyToBackupKey(key);
- currentIds.add(backupKey);
- if (!savedIds.contains(backupKey) || updateTime >= in.t) {
- byte[] blob = packScreen(cursor);
- writeRowToBackup(key, blob, out, data);
+ if (!mExistingKeys.contains(backupKey) || updateTime >= mLastBackupRestoreTime) {
+ writeRowToBackup(key, packScreen(cursor), data);
} else {
- if (VERBOSE) Log.v(TAG, "screen " + id + " was too old: " + updateTime);
+ if (VERBOSE) Log.v(TAG, "screen already backup up " + id);
}
}
} finally {
cursor.close();
}
- if (DEBUG) Log.d(TAG, "screen currentIds.size()=" + currentIds.size());
-
- // these IDs must have been deleted
- savedIds.removeAll(currentIds);
- out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
/**
@@ -415,40 +389,24 @@
* @param key identifier for the row
* @param buffer the serialized proto from the stream, may be larger than dataSize
* @param dataSize the size of the proto from the stream
- * @param keys keys to mark as clean in the notes for next backup
*/
- private void restoreScreen(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
+ private void restoreScreen(Key key, byte[] buffer, int dataSize) throws IOException {
if (VERBOSE) Log.v(TAG, "unpacking screen " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
- if (!mRestoreEnabled) {
- if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
- return;
- }
-
- try {
- ContentResolver cr = mContext.getContentResolver();
- ContentValues values = unpackScreen(buffer, 0, dataSize);
- cr.insert(WorkspaceScreens.CONTENT_URI, values);
-
- } catch (InvalidProtocolBufferNanoException e) {
- Log.e(TAG, "failed to decode screen", e);
- }
+ ContentResolver cr = mContext.getContentResolver();
+ ContentValues values = unpackScreen(buffer, dataSize);
+ cr.insert(WorkspaceScreens.CONTENT_URI, values);
}
/**
* Write all the static icon resources we need to render placeholders
* for a package that is not installed.
*
- * @param in notes from last backup
* @param data output stream for key/value pairs
- * @param out notes about this backup
- * @param keys keys to mark as clean in the notes for next backup
- * @throws IOException
*/
- private void backupIcons(Journal in, BackupDataOutput data, Journal out,
- ArrayList<Key> keys) throws IOException {
+ private void backupIcons(BackupDataOutput data) throws IOException {
// persist icons that haven't been persisted yet
if (!initializeIconCache()) {
dataChanged(); // try again later
@@ -458,21 +416,14 @@
final ContentResolver cr = mContext.getContentResolver();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
-
- // read the old ID set
- Set<String> savedIds = getSavedIdsByType(Key.ICON, in);
- if (DEBUG) Log.d(TAG, "icon savedIds.size()=" + savedIds.size());
+ int backupUpIconCount = 0;
// Don't backup apps in other profiles for now.
- int startRows = out.rows;
- if (DEBUG) Log.d(TAG, "starting here: " + startRows);
-
String where = "(" + Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPLICATION + " OR " +
Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_SHORTCUT + ") AND " +
getUserSelectionArg();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
where, null, null);
- Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
@@ -486,27 +437,26 @@
if (cn != null) {
key = getKey(Key.ICON, cn.flattenToShortString());
backupKey = keyToBackupKey(key);
- currentIds.add(backupKey);
} else {
Log.w(TAG, "empty intent on application favorite: " + id);
}
- if (savedIds.contains(backupKey)) {
- if (VERBOSE) Log.v(TAG, "already saved icon " + backupKey);
+ if (mExistingKeys.contains(backupKey)) {
+ if (DEBUG) Log.d(TAG, "already saved icon " + backupKey);
// remember that we already backed this up previously
- keys.add(key);
+ mKeys.add(key);
} else if (backupKey != null) {
- if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
- if ((out.rows - startRows) < MAX_ICONS_PER_PASS) {
- if (VERBOSE) Log.v(TAG, "saving icon " + backupKey);
+ if (DEBUG) Log.d(TAG, "I can count this high: " + backupUpIconCount);
+ if (backupUpIconCount < MAX_ICONS_PER_PASS) {
+ if (DEBUG) Log.d(TAG, "saving icon " + backupKey);
Bitmap icon = mIconCache.getIcon(intent, myUserHandle);
- keys.add(key);
if (icon != null && !mIconCache.isDefaultIcon(icon, myUserHandle)) {
- byte[] blob = packIcon(dpi, icon);
- writeRowToBackup(key, blob, out, data);
+ writeRowToBackup(key, packIcon(dpi, icon), data);
+ mKeys.add(key);
+ backupUpIconCount ++;
}
} else {
- if (VERBOSE) Log.d(TAG, "deferring icon backup " + backupKey);
+ if (VERBOSE) Log.v(TAG, "deferring icon backup " + backupKey);
// too many icons for this pass, request another.
dataChanged();
}
@@ -521,11 +471,6 @@
} finally {
cursor.close();
}
- if (DEBUG) Log.d(TAG, "icon currentIds.size()=" + currentIds.size());
-
- // these IDs must have been deleted
- savedIds.removeAll(currentIds);
- out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
/**
@@ -536,55 +481,32 @@
* @param key identifier for the row
* @param buffer the serialized proto from the stream, may be larger than dataSize
* @param dataSize the size of the proto from the stream
- * @param keys keys to mark as clean in the notes for next backup
*/
- private void restoreIcon(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
+ private void restoreIcon(Key key, byte[] buffer, int dataSize) throws IOException {
if (VERBOSE) Log.v(TAG, "unpacking icon " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
- try {
- Resource res = unpackIcon(buffer, 0, dataSize);
- if (DEBUG) {
- Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
- }
- if (DEBUG_PAYLOAD) {
- Log.d(TAG, "read " +
- Base64.encodeToString(res.data, 0, res.data.length,
- Base64.NO_WRAP));
- }
- Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
- if (icon == null) {
- Log.w(TAG, "failed to unpack icon for " + key.name);
- }
-
- if (!mRestoreEnabled) {
- if (VERBOSE) {
- Log.v(TAG, "restore not enabled: skipping database mutation");
- }
- return;
- } else {
- if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
- IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name),
- icon, res.dpi);
- }
- } catch (IOException e) {
- Log.d(TAG, "failed to save restored icon for: " + key.name, e);
+ Resource res = unpackProto(new Resource(), buffer, dataSize);
+ if (DEBUG) {
+ Log.d(TAG, "unpacked " + res.dpi + " dpi icon");
}
+ Bitmap icon = BitmapFactory.decodeByteArray(res.data, 0, res.data.length);
+ if (icon == null) {
+ Log.w(TAG, "failed to unpack icon for " + key.name);
+ }
+ if (VERBOSE) Log.v(TAG, "saving restored icon as: " + key.name);
+ IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(key.name), icon, res.dpi);
}
/**
* Write all the static widget resources we need to render placeholders
* for a package that is not installed.
*
- * @param in notes from last backup
* @param data output stream for key/value pairs
- * @param out notes about this backup
- * @param keys keys to mark as clean in the notes for next backup
* @throws IOException
*/
- private void backupWidgets(Journal in, BackupDataOutput data, Journal out,
- ArrayList<Key> keys) throws IOException {
+ private void backupWidgets(BackupDataOutput data) throws IOException {
// persist static widget info that hasn't been persisted yet
final LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
if (appState == null || !initializeIconCache()) {
@@ -597,18 +519,12 @@
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final DeviceProfile profile = appState.getDynamicGrid().getDeviceProfile();
if (DEBUG) Log.d(TAG, "cellWidthPx: " + profile.cellWidthPx);
+ int backupWidgetCount = 0;
- // read the old ID set
- Set<String> savedIds = getSavedIdsByType(Key.WIDGET, in);
- if (DEBUG) Log.d(TAG, "widgets savedIds.size()=" + savedIds.size());
-
- int startRows = out.rows;
- if (DEBUG) Log.d(TAG, "starting here: " + startRows);
String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET + " AND "
+ getUserSelectionArg();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
where, null, null);
- Set<String> currentIds = new HashSet<String>(cursor.getCount());
try {
cursor.moveToPosition(-1);
while(cursor.moveToNext()) {
@@ -622,27 +538,25 @@
if (provider != null) {
key = getKey(Key.WIDGET, providerName);
backupKey = keyToBackupKey(key);
- currentIds.add(backupKey);
} else {
Log.w(TAG, "empty intent on appwidget: " + id);
}
- if (savedIds.contains(backupKey)) {
- if (VERBOSE) Log.v(TAG, "already saved widget " + backupKey);
+ if (mExistingKeys.contains(backupKey)) {
+ if (DEBUG) Log.d(TAG, "already saved widget " + backupKey);
// remember that we already backed this up previously
- keys.add(key);
+ mKeys.add(key);
} else if (backupKey != null) {
- if (DEBUG) Log.d(TAG, "I can count this high: " + out.rows);
- if ((out.rows - startRows) < MAX_WIDGETS_PER_PASS) {
- if (VERBOSE) Log.v(TAG, "saving widget " + backupKey);
+ if (DEBUG) Log.d(TAG, "I can count this high: " + backupWidgetCount);
+ if (backupWidgetCount < MAX_WIDGETS_PER_PASS) {
+ if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
previewLoader.setPreviewSize(spanX * profile.cellWidthPx,
spanY * profile.cellHeightPx, widgetSpacingLayout);
- byte[] blob = packWidget(dpi, previewLoader, mIconCache, provider);
- keys.add(key);
- writeRowToBackup(key, blob, out, data);
-
+ writeRowToBackup(key, packWidget(dpi, previewLoader, mIconCache, provider), data);
+ mKeys.add(key);
+ backupWidgetCount ++;
} else {
- if (VERBOSE) Log.d(TAG, "deferring widget backup " + backupKey);
+ if (VERBOSE) Log.v(TAG, "deferring widget backup " + backupKey);
// too many widgets for this pass, request another.
dataChanged();
}
@@ -651,11 +565,6 @@
} finally {
cursor.close();
}
- if (DEBUG) Log.d(TAG, "widget currentIds.size()=" + currentIds.size());
-
- // these IDs must have been deleted
- savedIds.removeAll(currentIds);
- out.rows += removeDeletedKeysFromBackup(savedIds, data);
}
/**
@@ -666,35 +575,25 @@
* @param key identifier for the row
* @param buffer the serialized proto from the stream, may be larger than dataSize
* @param dataSize the size of the proto from the stream
- * @param keys keys to mark as clean in the notes for next backup
*/
- private void restoreWidget(Key key, byte[] buffer, int dataSize, ArrayList<Key> keys) {
+ private void restoreWidget(Key key, byte[] buffer, int dataSize) throws IOException {
if (VERBOSE) Log.v(TAG, "unpacking widget " + key.id);
if (DEBUG) Log.d(TAG, "read (" + buffer.length + "): " +
Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
- try {
- Widget widget = unpackWidget(buffer, 0, dataSize);
- if (DEBUG) Log.d(TAG, "unpacked " + widget.provider);
- if (widget.icon.data != null) {
- Bitmap icon = BitmapFactory
- .decodeByteArray(widget.icon.data, 0, widget.icon.data.length);
- if (icon == null) {
- Log.w(TAG, "failed to unpack widget icon for " + key.name);
- } else {
- IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(widget.provider),
- icon, widget.icon.dpi);
- }
- }
-
- if (!mRestoreEnabled) {
- if (VERBOSE) Log.v(TAG, "restore not enabled: skipping database mutation");
- return;
+ Widget widget = unpackProto(new Widget(), buffer, dataSize);
+ if (DEBUG) Log.d(TAG, "unpacked " + widget.provider);
+ if (widget.icon.data != null) {
+ Bitmap icon = BitmapFactory
+ .decodeByteArray(widget.icon.data, 0, widget.icon.data.length);
+ if (icon == null) {
+ Log.w(TAG, "failed to unpack widget icon for " + key.name);
} else {
- // future site of widget table mutation
+ IconCache.preloadIcon(mContext, ComponentName.unflattenFromString(widget.provider),
+ icon, widget.icon.dpi);
}
- } catch (InvalidProtocolBufferNanoException e) {
- Log.e(TAG, "failed to decode widget", e);
}
+
+ // future site of widget table mutation
}
/** create a new key, with an integer ID.
@@ -744,30 +643,6 @@
}
}
- private String getKeyName(Key key) {
- if (TextUtils.isEmpty(key.name)) {
- return Long.toString(key.id);
- } else {
- return key.name;
- }
-
- }
-
- private String geKeyType(Key key) {
- switch (key.type) {
- case Key.FAVORITE:
- return "favorite";
- case Key.SCREEN:
- return "screen";
- case Key.ICON:
- return "icon";
- case Key.WIDGET:
- return "widget";
- default:
- return "anonymous";
- }
- }
-
/** Compute the checksum over the important bits of a key. */
private long checkKey(Key key) {
CRC32 checksum = new CRC32();
@@ -781,7 +656,7 @@
}
/** Serialize a Favorite for persistence, including a checksum wrapper. */
- private byte[] packFavorite(Cursor c) {
+ private Favorite packFavorite(Cursor c) {
Favorite favorite = new Favorite();
favorite.id = c.getLong(ID_INDEX);
favorite.screen = c.getInt(SCREEN_INDEX);
@@ -819,7 +694,7 @@
favorite.intent = intent.toUri(0);
} catch (URISyntaxException e) {
Log.e(TAG, "Invalid intent", e);
- }
+ }
}
favorite.itemType = c.getInt(ITEM_TYPE_INDEX);
if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) {
@@ -830,16 +705,13 @@
}
}
- return writeCheckedBytes(favorite);
+ return favorite;
}
/** Deserialize a Favorite from persistence, after verifying checksum wrapper. */
- private ContentValues unpackFavorite(byte[] buffer, int offset, int dataSize)
+ private ContentValues unpackFavorite(byte[] buffer, int dataSize)
throws InvalidProtocolBufferNanoException {
- Favorite favorite = new Favorite();
- MessageNano.mergeFrom(favorite, readCheckedBytes(buffer, offset, dataSize));
- if (VERBOSE) Log.v(TAG, "unpacked favorite " + favorite.itemType + ", " +
- (TextUtils.isEmpty(favorite.title) ? favorite.id : favorite.title));
+ Favorite favorite = unpackProto(new Favorite(), buffer, dataSize);
ContentValues values = new ContentValues();
values.put(Favorites._ID, favorite.id);
values.put(Favorites.SCREEN, favorite.screen);
@@ -889,20 +761,17 @@
}
/** Serialize a Screen for persistence, including a checksum wrapper. */
- private byte[] packScreen(Cursor c) {
+ private Screen packScreen(Cursor c) {
Screen screen = new Screen();
screen.id = c.getLong(ID_INDEX);
screen.rank = c.getInt(SCREEN_RANK_INDEX);
-
- return writeCheckedBytes(screen);
+ return screen;
}
/** Deserialize a Screen from persistence, after verifying checksum wrapper. */
- private ContentValues unpackScreen(byte[] buffer, int offset, int dataSize)
+ private ContentValues unpackScreen(byte[] buffer, int dataSize)
throws InvalidProtocolBufferNanoException {
- Screen screen = new Screen();
- MessageNano.mergeFrom(screen, readCheckedBytes(buffer, offset, dataSize));
- if (VERBOSE) Log.v(TAG, "unpacked screen " + screen.id + "/" + screen.rank);
+ Screen screen = unpackProto(new Screen(), buffer, dataSize);
ContentValues values = new ContentValues();
values.put(WorkspaceScreens._ID, screen.id);
values.put(WorkspaceScreens.SCREEN_RANK, screen.rank);
@@ -910,27 +779,18 @@
}
/** Serialize an icon Resource for persistence, including a checksum wrapper. */
- private byte[] packIcon(int dpi, Bitmap icon) {
+ private Resource packIcon(int dpi, Bitmap icon) {
Resource res = new Resource();
res.dpi = dpi;
ByteArrayOutputStream os = new ByteArrayOutputStream();
if (icon.compress(IMAGE_FORMAT, IMAGE_COMPRESSION_QUALITY, os)) {
res.data = os.toByteArray();
}
- return writeCheckedBytes(res);
- }
-
- /** Deserialize an icon resource from persistence, after verifying checksum wrapper. */
- private static Resource unpackIcon(byte[] buffer, int offset, int dataSize)
- throws InvalidProtocolBufferNanoException {
- Resource res = new Resource();
- MessageNano.mergeFrom(res, readCheckedBytes(buffer, offset, dataSize));
- if (VERBOSE) Log.v(TAG, "unpacked icon " + res.dpi + "/" + res.data.length);
return res;
}
/** Serialize a widget for persistence, including a checksum wrapper. */
- private byte[] packWidget(int dpi, WidgetPreviewLoader previewLoader, IconCache iconCache,
+ private Widget packWidget(int dpi, WidgetPreviewLoader previewLoader, IconCache iconCache,
ComponentName provider) {
final AppWidgetProviderInfo info = findAppWidgetProviderInfo(provider);
Widget widget = new Widget();
@@ -956,16 +816,17 @@
widget.preview.dpi = dpi;
}
}
- return writeCheckedBytes(widget);
+ return widget;
}
- /** Deserialize a widget from persistence, after verifying checksum wrapper. */
- private Widget unpackWidget(byte[] buffer, int offset, int dataSize)
+ /**
+ * Deserialize a proto after verifying checksum wrapper.
+ */
+ private <T extends MessageNano> T unpackProto(T proto, byte[] buffer, int dataSize)
throws InvalidProtocolBufferNanoException {
- Widget widget = new Widget();
- MessageNano.mergeFrom(widget, readCheckedBytes(buffer, offset, dataSize));
- if (VERBOSE) Log.v(TAG, "unpacked widget " + widget.provider);
- return widget;
+ MessageNano.mergeFrom(proto, readCheckedBytes(buffer, dataSize));
+ if (DEBUG) Log.d(TAG, "unpacked proto " + proto);
+ return proto;
}
/**
@@ -1001,9 +862,6 @@
if (result > 0) {
availableBytes -= result;
bytesRead += result;
- if (DEBUG && (bytesRead % 100 == 0)) {
- Log.d(TAG, "read some bytes: " + bytesRead);
- }
} else {
Log.w(TAG, "unexpected end of file while reading journal.");
// stop reading and see what there is to parse
@@ -1016,7 +874,7 @@
// check the buffer to see if we have a valid journal
try {
- MessageNano.mergeFrom(journal, readCheckedBytes(buffer, 0, bytesRead));
+ MessageNano.mergeFrom(journal, readCheckedBytes(buffer, bytesRead));
// if we are here, then we have read a valid, checksum-verified journal
valid = true;
availableBytes = 0;
@@ -1044,46 +902,18 @@
return journal;
}
- private void writeRowToBackup(Key key, byte[] blob, Journal out,
+
+ private void writeRowToBackup(Key key, MessageNano proto, BackupDataOutput data)
+ throws IOException {
+ writeRowToBackup(keyToBackupKey(key), proto, data);
+ }
+
+ private void writeRowToBackup(String backupKey, MessageNano proto,
BackupDataOutput data) throws IOException {
- String backupKey = keyToBackupKey(key);
+ byte[] blob = writeCheckedBytes(proto);
data.writeEntityHeader(backupKey, blob.length);
data.writeEntityData(blob, blob.length);
- out.rows++;
- out.bytes += blob.length;
- if (VERBOSE) Log.v(TAG, "saving " + geKeyType(key) + " " + backupKey + ": " +
- getKeyName(key) + "/" + blob.length);
- if(DEBUG_PAYLOAD) {
- String encoded = Base64.encodeToString(blob, 0, blob.length, Base64.NO_WRAP);
- final int chunkSize = 1024;
- for (int offset = 0; offset < encoded.length(); offset += chunkSize) {
- int end = offset + chunkSize;
- end = Math.min(end, encoded.length());
- Log.w(TAG, "wrote " + encoded.substring(offset, end));
- }
- }
- }
-
- private Set<String> getSavedIdsByType(int type, Journal in) {
- Set<String> savedIds = new HashSet<String>();
- for(int i = 0; i < in.key.length; i++) {
- Key key = in.key[i];
- if (key.type == type) {
- savedIds.add(keyToBackupKey(key));
- }
- }
- return savedIds;
- }
-
- private int removeDeletedKeysFromBackup(Set<String> deletedIds, BackupDataOutput data)
- throws IOException {
- int rows = 0;
- for(String deleted: deletedIds) {
- if (VERBOSE) Log.v(TAG, "dropping deleted item " + deleted);
- data.writeEntityHeader(deleted, -1);
- rows++;
- }
- return rows;
+ if (VERBOSE) Log.v(TAG, "Writing New entry " + backupKey);
}
/**
@@ -1119,10 +949,10 @@
}
/** Unwrap a proto message from a CheckedMessage, verifying the checksum. */
- private static byte[] readCheckedBytes(byte[] buffer, int offset, int dataSize)
+ private static byte[] readCheckedBytes(byte[] buffer, int dataSize)
throws InvalidProtocolBufferNanoException {
CheckedMessage wrapper = new CheckedMessage();
- MessageNano.mergeFrom(wrapper, buffer, offset, dataSize);
+ MessageNano.mergeFrom(wrapper, buffer, 0, dataSize);
CRC32 checksum = new CRC32();
checksum.update(wrapper.payload);
if (wrapper.checksum != checksum.getValue()) {
@@ -1161,7 +991,9 @@
}
- // check if the launcher is in a state to support backup
+ /**
+ * @return true if the launcher is in a state to support backup
+ */
private boolean launcherIsReady() {
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, null, null, null);
@@ -1185,7 +1017,7 @@
.getSerialNumberForUser(UserHandleCompat.myUserHandle());
}
- private class KeyParsingException extends Throwable {
+ private class KeyParsingException extends IOException {
private KeyParsingException(Throwable cause) {
super(cause);
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index e0cfa27..a1f4e0b 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -98,11 +98,11 @@
/**
* Handshake to establish an overlay relationship
*
- * @param overlayView Full screen overlay ViewGroup into which custom views can be placed.
+ * @param container Full screen overlay ViewGroup into which custom views can be placed.
* @param callbacks A set of callbacks provided by Launcher in relation to the overlay
* @return an interface used to make requests and notify the Launcher in relation to the overlay
*/
- public Launcher.LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
+ public Launcher.LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
Launcher.LauncherOverlayCallbacks callbacks);
}
diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java
index 10bbd35..b264042 100644
--- a/src/com/android/launcher3/LauncherExtension.java
+++ b/src/com/android/launcher3/LauncherExtension.java
@@ -252,11 +252,11 @@
}
@Override
- public LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
+ public LauncherOverlay setLauncherOverlayView(InsettableFrameLayout container,
LauncherOverlayCallbacks callbacks) {
mLauncherOverlay.setOverlayCallbacks(callbacks);
- mLauncherOverlay.setOverlayView(overlayView);
+ mLauncherOverlay.setOverlayContainer(container);
return mLauncherOverlay;
}
@@ -335,9 +335,9 @@
hideOverlayPanel();
}
- public void setOverlayView(ViewGroup overlayView) {
+ public void setOverlayContainer(InsettableFrameLayout container) {
mOverlayView = (ViewGroup) getLayoutInflater().inflate(
- R.layout.launcher_overlay_example, overlayView);
+ R.layout.launcher_overlay_example, container);
mSearchOverlay = mOverlayView.findViewById(R.id.search_overlay);
mSearchBox = mOverlayView.findViewById(R.id.search_box);
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 9150dc0..f2d005e 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -1480,9 +1480,13 @@
// Canonicalize
// the Play Store sets the package parameter, but Launcher
- // does not, so we clear that out to keep them the same
+ // does not, so we clear that out to keep them the same.
+ // Also ignore intent flags for the purposes of deduping.
intent.setPackage(null);
+ int flags = intent.getFlags();
+ intent.setFlags(0);
final String key = intent.toUri(0);
+ intent.setFlags(flags);
if (seenIntents.contains(key)) {
Launcher.addDumpLog(TAG, "skipping duplicate", true);
continue;
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
new file mode 100644
index 0000000..e8c11c4
--- /dev/null
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -0,0 +1,17 @@
+package com.android.launcher3;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+
+public class LauncherRootView extends InsettableFrameLayout {
+ public LauncherRootView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ setInsets(insets);
+ return true; // I'll take it from here
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 518ee97..66d4ac0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -295,6 +295,7 @@
boolean mScrollInteractionBegan;
boolean mStartedSendingScrollEvents;
boolean mShouldSendPageSettled;
+ int mLastOverlaySroll = 0;
private final Runnable mBindPages = new Runnable() {
@Override
@@ -1287,8 +1288,11 @@
boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) ||
(amount >= 0 && (!hasCustomContent() || !isRtl));
- boolean shouldScrollOverlay = (amount <= 0 && mLauncherOverlay != null && !isRtl) ||
- (amount >= 0 && mLauncherOverlay != null && isRtl);
+ boolean shouldScrollOverlay = mLauncherOverlay != null &&
+ ((amount <= 0 && !isRtl) || (amount >= 0 && isRtl));
+
+ boolean shouldZeroOverlay = mLauncherOverlay != null && mLastOverlaySroll != 0 &&
+ ((amount >= 0 && !isRtl) || (amount <= 0 && isRtl));
if (shouldScrollOverlay) {
if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
@@ -1301,6 +1305,7 @@
int progress = (int) Math.abs((f * 100));
+ mLastOverlaySroll = progress;
mLauncherOverlay.onScrollChange(progress, isRtl);
} else if (shouldOverScroll) {
dampedOverScroll(amount);
@@ -1308,6 +1313,10 @@
} else {
mOverScrollEffect = 0;
}
+
+ if (shouldZeroOverlay) {
+ mLauncherOverlay.onScrollChange(0, isRtl);
+ }
}
@Override