Merge "Deleting workspace items from db which have an invalid placement" into ub-now-queens
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 591d9b6..fb7ac3f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -88,7 +88,25 @@
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:windowSoftInputMode="adjustPan"
- android:screenOrientation="nosensor">
+ android:screenOrientation="nosensor"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.MONKEY"/>
+ </intent-filter>
+ </activity>
+
+ <activity
+ android:name="com.android.launcher3.LauncherExtension"
+ android:launchMode="singleTask"
+ android:clearTaskOnLaunch="true"
+ android:stateNotNeeded="true"
+ android:theme="@style/Theme"
+ android:windowSoftInputMode="adjustPan"
+ android:screenOrientation="nosensor"
+ android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
diff --git a/res/drawable-hdpi/hand.png b/res/drawable-hdpi/hand.png
deleted file mode 100644
index bd4f6df..0000000
--- a/res/drawable-hdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_focused_holo.9.png b/res/drawable-hdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 673e3bf..0000000
--- a/res/drawable-hdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_holo.9.png b/res/drawable-hdpi/tab_selected_holo.9.png
deleted file mode 100644
index d57df98..0000000
--- a/res/drawable-hdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 4b312d9..0000000
--- a/res/drawable-hdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_selected_pressed_holo.9.png b/res/drawable-hdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 6278eef..0000000
--- a/res/drawable-hdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index 294991d..0000000
--- a/res/drawable-hdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_holo.9.png b/res/drawable-hdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 19532ab..0000000
--- a/res/drawable-hdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index 5140b35..0000000
--- a/res/drawable-hdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png b/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index aadc6f8..0000000
--- a/res/drawable-hdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/hand.png b/res/drawable-mdpi/hand.png
deleted file mode 100644
index fe5a035..0000000
--- a/res/drawable-mdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_focused_holo.9.png b/res/drawable-mdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index c9972e7..0000000
--- a/res/drawable-mdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_holo.9.png b/res/drawable-mdpi/tab_selected_holo.9.png
deleted file mode 100644
index 587337c..0000000
--- a/res/drawable-mdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 284f534..0000000
--- a/res/drawable-mdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_selected_pressed_holo.9.png b/res/drawable-mdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 155c4fc..0000000
--- a/res/drawable-mdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index f0cecd1..0000000
--- a/res/drawable-mdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_holo.9.png b/res/drawable-mdpi/tab_unselected_holo.9.png
deleted file mode 100644
index a2dbf42..0000000
--- a/res/drawable-mdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index f1a2819..0000000
--- a/res/drawable-mdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png b/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index b1223fe..0000000
--- a/res/drawable-mdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/hand.png b/res/drawable-xhdpi/hand.png
deleted file mode 100644
index 35b678c..0000000
--- a/res/drawable-xhdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_focused_holo.9.png b/res/drawable-xhdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 03cfb09..0000000
--- a/res/drawable-xhdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_holo.9.png b/res/drawable-xhdpi/tab_selected_holo.9.png
deleted file mode 100644
index e4229f2..0000000
--- a/res/drawable-xhdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png b/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png
deleted file mode 100644
index 2412711..0000000
--- a/res/drawable-xhdpi/tab_selected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_selected_pressed_holo.9.png b/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index e862cb1..0000000
--- a/res/drawable-xhdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_focused_holo.9.png b/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index f3a5cbd..0000000
--- a/res/drawable-xhdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_holo.9.png b/res/drawable-xhdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 9465173..0000000
--- a/res/drawable-xhdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png b/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png
deleted file mode 100644
index 1653600..0000000
--- a/res/drawable-xhdpi/tab_unselected_pressed_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png b/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index f1eb673..0000000
--- a/res/drawable-xhdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/hand.png b/res/drawable-xxhdpi/hand.png
deleted file mode 100644
index 88c2a88..0000000
--- a/res/drawable-xxhdpi/hand.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_focused_holo.9.png b/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
deleted file mode 100644
index 2400c65..0000000
--- a/res/drawable-xxhdpi/tab_selected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_holo.9.png b/res/drawable-xxhdpi/tab_selected_holo.9.png
deleted file mode 100644
index 5067cbb..0000000
--- a/res/drawable-xxhdpi/tab_selected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png b/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
deleted file mode 100644
index 84c246d..0000000
--- a/res/drawable-xxhdpi/tab_selected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png b/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
deleted file mode 100644
index 939e0c3..0000000
--- a/res/drawable-xxhdpi/tab_unselected_focused_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_holo.9.png b/res/drawable-xxhdpi/tab_unselected_holo.9.png
deleted file mode 100644
index 62ca6cf..0000000
--- a/res/drawable-xxhdpi/tab_unselected_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png b/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
deleted file mode 100644
index 58ac0d6..0000000
--- a/res/drawable-xxhdpi/tab_unselected_pressed_holo.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/tab_widget_indicator_selector.xml b/res/drawable/tab_widget_indicator_selector.xml
deleted file mode 100644
index d06f757..0000000
--- a/res/drawable/tab_widget_indicator_selector.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <!-- Non focused states -->
- <item android:state_focused="false" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_holo" />
-
- <!-- Focused states -->
- <item android:state_focused="true" android:state_selected="false" android:state_pressed="false" android:drawable="@drawable/tab_unselected_focused_holo" />
- <item android:state_focused="true" android:state_selected="true" android:state_pressed="false" android:drawable="@drawable/tab_selected_focused_holo" />
-
- <!-- Pressed -->
- <!-- Non focused states -->
- <item android:state_focused="false" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_holo" />
- <item android:state_focused="false" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_holo" />
-
- <!-- Focused states -->
- <item android:state_focused="true" android:state_selected="false" android:state_pressed="true" android:drawable="@drawable/tab_unselected_pressed_focused_holo" />
- <item android:state_focused="true" android:state_selected="true" android:state_pressed="true" android:drawable="@drawable/tab_selected_pressed_focused_holo" />
-</selector>
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 8cd8673..fa5fe73 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -63,4 +63,11 @@
android:layout_height="match_parent"
android:visibility="invisible" />
</com.android.launcher3.DragLayer>
+
+ <ViewStub
+ android:id="@+id/launcher_overlay_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:inflatedId="@+id/launcher_overlay"
+ android:layout="@layout/launcher_overlay" />
</FrameLayout>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 9e98d42..f2d2dd8 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -83,4 +83,11 @@
android:layout_height="match_parent"
android:visibility="invisible" />
</com.android.launcher3.DragLayer>
+
+ <ViewStub
+ android:id="@+id/launcher_overlay_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:inflatedId="@+id/launcher_overlay"
+ android:layout="@layout/launcher_overlay" />
</FrameLayout>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 6261541..87fa2ed 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -82,4 +82,12 @@
android:layout_height="match_parent"
android:visibility="invisible" />
</com.android.launcher3.DragLayer>
+
+ <ViewStub
+ android:id="@+id/launcher_overlay_stub"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:inflatedId="@+id/launcher_overlay"
+ android:layout="@layout/launcher_overlay" />
+
</FrameLayout>
diff --git a/res/layout-sw720dp/market_button.xml b/res/layout-sw720dp/market_button.xml
deleted file mode 100644
index 7eaeafa..0000000
--- a/res/layout-sw720dp/market_button.xml
+++ /dev/null
@@ -1,36 +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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/MarketButton"
- android:onClick="onClickAppMarketButton"
- android:gravity="center"
- android:paddingLeft="32dp"
- android:paddingRight="32dp"
- android:drawablePadding="10dp"
- android:background="@drawable/tab_widget_indicator_selector"
- android:text="@string/market"
- android:contentDescription="@string/market"
- android:textColor="@color/workspace_all_apps_and_delete_zone_text_color"
- android:textStyle="bold"
- android:textSize="14sp"
- android:textAllCaps="true"
- android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
- android:shadowDx="0.0"
- android:shadowDy="0.0"
- android:shadowRadius="2.0"
- android:focusable="true"
- android:clickable="true" />
diff --git a/res/layout/tab_widget_indicator.xml b/res/layout/launcher_overlay.xml
similarity index 81%
rename from res/layout/tab_widget_indicator.xml
rename to res/layout/launcher_overlay.xml
index de7c50e..9ef0c9a 100644
--- a/res/layout/tab_widget_indicator.xml
+++ b/res/layout/launcher_overlay.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
+<!-- Copyright (C) 2008 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,6 +14,7 @@
limitations under the License.
-->
-<com.android.launcher3.AccessibleTabView
+<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/TabIndicator.AppsCustomize" />
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/launcher_overlay_example.xml b/res/layout/launcher_overlay_example.xml
new file mode 100644
index 0000000..422f281
--- /dev/null
+++ b/res/layout/launcher_overlay_example.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <FrameLayout
+ android:id="@+id/search_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#ff00ff00"
+ android:visibility="invisible" />
+
+ <FrameLayout
+ android:id="@+id/search_box"
+ android:layout_width="match_parent"
+ android:layout_height="48dp"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="8dp"
+ android:layout_marginTop="36dp"
+ android:background="#ffff0000" />
+</FrameLayout>
diff --git a/res/layout/market_button.xml b/res/layout/market_button.xml
deleted file mode 100644
index 41e6ec7..0000000
--- a/res/layout/market_button.xml
+++ /dev/null
@@ -1,30 +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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/MarketButton"
- android:onClick="onClickAppMarketButton"
- android:gravity="center"
- android:paddingLeft="16dp"
- android:paddingRight="16dp"
- android:background="@drawable/tab_widget_indicator_selector"
- android:contentDescription="@string/market"
- android:shadowColor="@color/workspace_all_apps_and_delete_zone_text_shadow_color"
- android:shadowDx="0.0"
- android:shadowDy="0.0"
- android:shadowRadius="2.0"
- android:focusable="true"
- android:clickable="true" />
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 558900c..4b7423e 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
+<!--
+ Copyright (C) 2013 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -13,47 +14,50 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
- android:orientation="horizontal">
+ android:gravity="top"
+ android:orientation="horizontal" >
<TextView
android:id="@+id/wallpaper_button"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_gravity="start|top"
- android:text="@string/wallpaper_button_text"
+ android:layout_weight="1"
android:drawablePadding="4dp"
android:drawableTop="@drawable/wallpaper_button"
- android:gravity="center_horizontal"
android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:text="@string/wallpaper_button_text"
android:textAllCaps="true"
android:textSize="12sp" />
+
<TextView
android:id="@+id/widget_button"
- android:layout_width="wrap_content"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:text="@string/widget_button_text"
+ android:layout_weight="1"
android:drawablePadding="4dp"
- android:gravity="center_horizontal"
android:drawableTop="@drawable/widget_button"
android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp"/>
- <TextView
- android:id="@+id/settings_button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="end|top"
- android:text="@string/settings_button_text"
- android:drawablePadding="4dp"
android:gravity="center_horizontal"
- android:drawableTop="@drawable/setting_button"
- android:fontFamily="sans-serif-condensed"
+ android:text="@string/widget_button_text"
android:textAllCaps="true"
android:textSize="12sp" />
-</FrameLayout>
+
+ <TextView
+ android:id="@+id/settings_button"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/setting_button"
+ android:fontFamily="sans-serif-condensed"
+ android:gravity="center_horizontal"
+ android:text="@string/settings_button_text"
+ android:textAllCaps="true"
+ android:textSize="12sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 1c75b5a..8aa65a4 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Raak en hou om \'n legstuk op te tel."</string>
- <string name="market" msgid="2619650989819296998">"Winkel"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Kan nie item op hierdie Tuisskerm laat los nie."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Kies legstuk om te skep"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 5938bf0..0326109 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ፍርግሞች"</string>
<string name="widget_adder" msgid="3201040140710381657">"ፍርግሞች"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ማህደረ ማስታወሻ አሳይ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ፍርግም ለማንሳት ይንኩ እና ይያዙት"</string>
- <string name="market" msgid="2619650989819296998">"ግዛ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"ንጥሉን እዚህ የመነሻ ማያ ገጽ ላይ ማኖር አልተቻለም።"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ለመፍጠር መግብር ይምረጡ"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 41184a5..919f0d0 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"الأدوات"</string>
<string name="widget_adder" msgid="3201040140710381657">"الأدوات"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"عرض الذاكرة"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"المس مع الاستمرار لاختيار إحدى الأدوات."</string>
- <string name="market" msgid="2619650989819296998">"تسوق"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"تعذر إسقاط العنصر على هذه الشاشة الرئيسية."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"اختيار أداة لإنشائها"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 05c5a7d..6654f1d 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Приспособления"</string>
<string name="widget_adder" msgid="3201040140710381657">"Приспособления"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Показване на паметта"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Докоснете и задръжте за избор на приспособление."</string>
- <string name="market" msgid="2619650989819296998">"Пазаруване"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Не можа да се премести на този начален екран."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор на приспособл. за създаване"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 616a316..019e82f 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"L\'aplicació no s\'ha instal·lat."</string>
<string name="activity_not_available" msgid="7456344436509528827">"L\'aplicació no està disponible."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'aplicació que has baixat està desactivada al mode segur."</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"En Mode segur, els widgets estan desactivats."</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">"Mostra la memòria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén premut un widget per triar-lo."</string>
- <string name="market" msgid="2619650989819296998">"Compra"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"No s\'ha pogut deixar anar l\'element a Inici."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Tria el widget que vulguis crear"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 9bce2e3..4b05436 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget vyberete dotykem a podržením."</string>
- <string name="market" msgid="2619650989819296998">"Obchod"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Na tuto plochu položku nelze přesunout."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vyberte widget k vytvoření"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 216a01d..d5352f2 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryk på en widget, og hold den nede for at vælge."</string>
- <string name="market" msgid="2619650989819296998">"Køb i Google Play Butik"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Elementet kunne ikke trækkes til startskærmen."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Vælg den widget, du vil oprette"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index eda4920..7e4ae47 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"App ist nicht installiert."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App nicht verfügbar"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Heruntergeladene App im abgesicherten Modus deaktiviert"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets im abgesicherten Modus deaktiviert"</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">"Speicher anzeigen"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Zum Hinzufügen Widget berühren und halten"</string>
- <string name="market" msgid="2619650989819296998">"Einkaufen"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Element wurde nicht auf diesem Startbildschirm abgelegt."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget zum Erstellen auswählen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 4567ea6..5a36332 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Γραφικά στοιχεία"</string>
<string name="widget_adder" msgid="3201040140710381657">"Γραφικά στοιχεία"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Εμφάνιση Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Αγγίξτε παρατεταμένα για να πάρετε ένα γραφ.στοιχ."</string>
- <string name="market" msgid="2619650989819296998">"Αγορά"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Αδυναμία τοποθέτησης στοιχείου στην Αρχική οθόνη."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Επιλ. γραφ. στοιχείο για δημιουργία"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index bf10a22..7e21222 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</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">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch & hold to pick up a widget."</string>
- <string name="market" msgid="2619650989819296998">"Shop"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index bf10a22..7e21222 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"App isn\'t installed."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App isn\'t available"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Downloaded app disabled in Safe mode"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets disabled in Safe mode"</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">"Show Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Touch & hold to pick up a widget."</string>
- <string name="market" msgid="2619650989819296998">"Shop"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Couldn\'t drop item on this Home screen."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Choose widget to create"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 79eb9a1..dc43f2d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén presionado el widget que desees elegir."</string>
- <string name="market" msgid="2619650989819296998">"Comprar"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Error al soltar elemento en la pantalla principal"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Elegir los widgets para crear"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 2914482..67c283a 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"La aplicación no está instalada."</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>
+ <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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Mantén pulsado el widget que quieras seleccionar."</string>
- <string name="market" msgid="2619650989819296998">"Tienda"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Error al arrastrar elemento a pantalla de inicio."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecciona widget a añadir"</string>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index 8943b34..1b9f1b7 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Rakendus pole installitud."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Rakendus ei ole saadaval"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Allalaetud rakendus on turvarežiimis keelatud"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Turvarežiimis on vidinad keelatud"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Vidinad"</string>
<string name="widget_adder" msgid="3201040140710381657">"Vidinad"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mälu kuvamine"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Vidina valimiseks vajutage ja hoidke seda all."</string>
- <string name="market" msgid="2619650989819296998">"Pood"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Üksust ei saanud sellele avaekraanile tuua."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valige loomiseks vidin"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 6607843..c765d8f 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ابزارکها"</string>
<string name="widget_adder" msgid="3201040140710381657">"ابزارکها"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"نمایش Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"برای انتخاب ابزارک لمس کنید و نگه دارید."</string>
- <string name="market" msgid="2619650989819296998">"فروشگاه"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"این مورد را نمیتوان در این صفحه اصلی رها کرد."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"انتخاب ابزارکی که باید ایجاد شود"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index eccb06e..0004501 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Sovellusta ei ole asennettu."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Sovellus ei ole käytettävissä"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ladattu sovellus poistettiin käytöstä suojatussa tilassa"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgetit poistettu käytöstä vikasietotilassa"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgetit"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgetit"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Näytä muisti"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Valitse widget painamalla sitä pitkään."</string>
- <string name="market" msgid="2619650989819296998">"Kauppa"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Kohteen lisääminen tähän aloitusruutuun epäonnistui."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Valitse luotava widget"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index aac11ed..c1070f2 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Maintenez un doigt sur le widget pour l\'ajouter."</string>
- <string name="market" msgid="2619650989819296998">"Magasiner"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Imposs. de déposer l\'élément sur l\'écran d\'accueil"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionnez le widget à créer"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b2eee99..064d751 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"App. de manière prolongée pour sélectionner widget."</string>
- <string name="market" msgid="2619650989819296998">"Boutique"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Impossible de déposer élément sur écran d\'accueil."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Sélectionner le widget à créer"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index ac0681f..f14eff7 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"विजेट"</string>
- <string name="widget_adder" msgid="3201040140710381657">"विजेट"</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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"विजेट को चुनने के लिए स्पर्श करके रखें."</string>
- <string name="market" msgid="2619650989819296998">"खरीदारी करें"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"आइटम को इस होम स्क्रीन पर नहीं छोड़ा जा सका."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"बनाने के लिए विजेट चुनें"</string>
@@ -41,7 +41,7 @@
<string name="menu_item_add_item" msgid="1264911265836810421">"होम स्क्रीन में जोड़ें"</string>
<string name="group_applications" msgid="3797214114206693605">"ऐप्लिकेशन"</string>
<string name="group_shortcuts" msgid="6012256992764410535">"शॉर्टकट"</string>
- <string name="group_widgets" msgid="1569030723286851002">"विजेट"</string>
+ <string name="group_widgets" msgid="1569030723286851002">"शॉर्टकट"</string>
<string name="completely_out_of_space" msgid="6106288382070760318">"आपकी होम स्क्रीन पर स्थान शेष नहीं है."</string>
<string name="out_of_space" msgid="4691004494942118364">"इस होम स्क्रीन पर स्थान शेष नहीं है."</string>
<string name="hotseat_out_of_space" msgid="7448809638125333693">"पसंदीदा ट्रे में और स्थान नहीं है"</string>
@@ -86,7 +86,7 @@
<string name="default_scroll_format" msgid="7475544710230993317">"पृष्ठ %2$d में से %1$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"होम स्क्रीन %2$d में से %1$d"</string>
<string name="apps_customize_apps_scroll_format" msgid="370005296147130238">"ऐप्लिकेशन पृष्ठ %2$d में से %1$d"</string>
- <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"विजेट पृष्ठ %2$d में से %1$d"</string>
+ <string name="apps_customize_widgets_scroll_format" msgid="3106209519974971521">"शॉर्टकट %2$d में से %1$d"</string>
<string name="first_run_cling_title" msgid="2459738000155917941">"स्वागत है"</string>
<string name="first_run_cling_description" msgid="6447072552696253358">"जैसा चाहें वैसा उपयोग करें."</string>
<string name="first_run_cling_custom_content_hint" msgid="6090628589029352439"></string>
@@ -97,8 +97,8 @@
<string name="migration_cling_copy_apps" msgid="946331230090919440">"आइकन की प्रतिलिपि बनाएं"</string>
<string name="migration_cling_use_default" msgid="2626475813981258626">"फिर से शुरू करें"</string>
<string name="workspace_cling_title" msgid="5626202359865825661">"अपने स्थान को व्यवस्थित करें"</string>
- <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, विजेट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
- <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, विजेट और सेटिंग"</string>
+ <string name="workspace_cling_move_item" msgid="528201129978005352">"वॉलपेपर, शॉर्टकट और सेटिंग प्रबंधित करने के लिए पृष्ठभूमि को स्पर्श करके रखें."</string>
+ <string name="workspace_cling_longpress_title" msgid="9173998993909018310">"वॉलपेपर, शॉर्टकट और सेटिंग"</string>
<string name="workspace_cling_longpress_description" msgid="4119994475505235248">"पृष्ठभूमि कस्टमाइज़ करने के लिए स्पर्श करके रखें"</string>
<string name="workspace_cling_longpress_dismiss" msgid="368660286867640874">"समझ लिया"</string>
<string name="folder_cling_title" msgid="3894908818693254164">"यहां एक फ़ोल्डर है"</string>
@@ -110,7 +110,7 @@
<string name="folder_closed" msgid="4100806530910930934">"फ़ोल्डर बंद किया गया"</string>
<string name="folder_renamed" msgid="1794088362165669656">"फ़ोल्डर का नाम बदलकर <xliff:g id="NAME">%1$s</xliff:g> किया गया"</string>
<string name="folder_name_format" msgid="6629239338071103179">"फ़ोल्डर: <xliff:g id="NAME">%1$s</xliff:g>"</string>
- <string name="widget_button_text" msgid="2880537293434387943">"विजेट"</string>
+ <string name="widget_button_text" msgid="2880537293434387943">"शॉर्टकट"</string>
<string name="wallpaper_button_text" msgid="8404103075899945851">"वॉलपेपर"</string>
<string name="settings_button_text" msgid="8119458837558863227">"सेटिंग"</string>
<string name="package_state_enqueued" msgid="6227252464303085641">"प्रतीक्षा में"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 6e69684..aa01648 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacija nije instalirana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacija nije dostupna"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Preuzeta aplikacija onemogućena je u Sigurnom načinu rada"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgeti su onemogućeni u Sigurnom načinu rada"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgeti"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgeti"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Prikaži mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Dodirnite i držite kako biste podigli widget."</string>
- <string name="market" msgid="2619650989819296998">"Kupi"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Stavka nije ispuštena na ovaj početni zaslon."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Odabir widgeta za stvaranje"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 1c11865..4416ab0 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Az alkalmazás nincs telepítve."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Az alkalmazás nem érhető el"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"A letöltött alkalmazás Csökkentett módban ki van kapcsolva"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"A modulok ki vannak kapcsolva Csökkentett módban"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Modulok"</string>
<string name="widget_adder" msgid="3201040140710381657">"Modulok"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem. megjelenítése"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Modul felvételéhez érintse meg, és tartsa lenyomva"</string>
- <string name="market" msgid="2619650989819296998">"Vásárlás"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Nem lehet elemeket dobni erre a kezdőképernyőre."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"A létrehozáshoz válasszon modult"</string>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index be5568c..9402a42 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Վիջեթներ"</string>
<string name="widget_adder" msgid="3201040140710381657">"Վիջեթներ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Ցուցադրել մեմը"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Հպեք և պահեք՝ վիջեթն ընտրելու համար:"</string>
- <string name="market" msgid="2619650989819296998">"Խանութ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Հնարավոր չէ տեղադրել տարրն այս հիմնական էկրանին:"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ստեղծելու համար ընտրեք վիջեթը"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0aadeb3..2eb88c7 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikasi tidak dipasang."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikasi tidak tersedia"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplikasi yang diunduh dinonaktifkan dalam mode Aman"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widget dinonaktifkan dalam mode Aman"</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">"Tampilkan Memori"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh lama untuk memilih widget."</string>
- <string name="market" msgid="2619650989819296998">"Belanja"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepas item ke layar Utama ini."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget untuk membuat"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 77242dd..aaddcfc 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"App non installata."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App non disponibile"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"L\'app scaricata è stata disattivata in modalità provvisoria"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widget disabilitati in modalità provvisoria"</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">"Mostra Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tocca e tieni premuto per scegliere un widget."</string>
- <string name="market" msgid="2619650989819296998">"Acquista"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Rilascio elemento in schermata Home non riuscito."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Scegli il widget da creare"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 02012ce..fc059e0 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"רכיבי ווידג\'ט"</string>
<string name="widget_adder" msgid="3201040140710381657">"רכיבי ווידג\'ט"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"הצג זכרון"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"גע נגיעה רציפה בווידג\'ט כדי לבחור בו."</string>
- <string name="market" msgid="2619650989819296998">"קנה"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"לא ניתן היה לשחרר את הפריט במסך דף הבית הזה."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"בחר ווידג\'ט ליצירה"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 3ce781b..d8ee943 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ウィジェット"</string>
<string name="widget_adder" msgid="3201040140710381657">"ウィジェット"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"メモリーを表示"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ウィジェットを追加するには押し続けます。"</string>
- <string name="market" msgid="2619650989819296998">"ショップ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"このホーム画面にアイテムをドロップできませんでした"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"作成するウィジェットの選択"</string>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 31cdb40..8092331 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ვიჯეტები"</string>
<string name="widget_adder" msgid="3201040140710381657">"ვიჯეტები"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Mem-ის ჩვენება"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"შეეხეთ და დააყოვნეთ ვიჯეტის ასარჩევად."</string>
- <string name="market" msgid="2619650989819296998">"მაღაზია"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"ერთეულის მთავარ ეკრანზე ჩაგდება ვერ მოხერხდა."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"აირჩიეთ ვიჯეტი შესაქმნელად"</string>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 19dd31e..390f0ee 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ធាតុក្រាហ្វិក"</string>
<string name="widget_adder" msgid="3201040140710381657">"ធាតុក្រាហ្វិក"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"បង្ហាញ Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ប៉ះ & សង្កត់ ដើម្បីជ្រើសធាតុក្រាហ្វិក។"</string>
- <string name="market" msgid="2619650989819296998">"ហាងទំនិញ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"មិនអាចទម្លាក់ធាតុលើអេក្រង់ដើមនេះទេ"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ជ្រើសធាតុក្រាហ្វិក ដើម្បីបង្កើត"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 88ea54e..d470283 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"위젯"</string>
<string name="widget_adder" msgid="3201040140710381657">"위젯"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"메모리 표시"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"위젯을 선택하려면 길게 터치하세요."</string>
- <string name="market" msgid="2619650989819296998">"쇼핑하기"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"홈 화면에 항목을 놓을 수 없습니다."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"만들 위젯 선택"</string>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index 87a7444..ac210d7 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -40,9 +40,5 @@
<item name="android:shadowRadius">4.0</item>
</style>
-<!-- AppsCustomize -->
- <style name="TabIndicator.AppsCustomize">
- <item name="android:maxWidth">200dp</item>
- </style>
</resources>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index b30a69d..935e997 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"ວິດເຈັດ"</string>
<string name="widget_adder" msgid="3201040140710381657">"ວິດເຈັດ"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"ສະແດງຄວາມຈຳ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"ສຳພັດຄ້າງໄວ້ ເພື່ອຈັບວິດເຈັດ."</string>
- <string name="market" msgid="2619650989819296998">"ຮ້ານຄ້າ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"ບໍ່ສາມາດວາງລາຍການໃສ່ໜ້າຈໍຫຼັກນີ້ໄດ້"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"ເລືອກວິດເຈັດເພື່ອສ້າງມັນ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 72b029c..6e47f67 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Programa neįdiegta."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Programa nepasiekiama"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Atsisiųsta programa išjungta Saugos režimu"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Valdikliai išjungti Saugiame režime"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Valdikliai"</string>
<string name="widget_adder" msgid="3201040140710381657">"Valdikliai"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Rodyti atmintinę"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Palieskite ir laikykite, kad pasirinkt. valdiklį."</string>
- <string name="market" msgid="2619650989819296998">"Apsipirkti"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Nepavyko nuvilkti elemento į šį pagrindinį ekraną."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pasirinkite norimą kurti valdiklį"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 280bc0c..4079331 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Lietotne nav instalēta."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Lietotne nav pieejama."</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Lejupielādētā lietotne ir atspējota drošajā režīmā."</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Logrīki atspējoti drošajā režīmā"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Logrīki"</string>
<string name="widget_adder" msgid="3201040140710381657">"Logrīki"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Rādīt atmiņu"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Lai izvēlētos logrīku, pieskarieties un turiet to."</string>
- <string name="market" msgid="2619650989819296998">"Iepirkties"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Nevarēja nomest vienumu šajā sākuma ekrānā."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izveidojamā logrīka izvēle"</string>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index 816803a..a22b8fc 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -26,11 +26,11 @@
<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">"Safe горимд виджетүүдийг идэвхгүйжүүлсэн"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Виджет"</string>
<string name="widget_adder" msgid="3201040140710381657">"Виджет"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Мем харуулах"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Виджетийг авах бол хүрээд барина уу."</string>
- <string name="market" msgid="2619650989819296998">"Дэлгүүр"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Энэ Нүүр дэлгэцэнд буулгах боломжгүй."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Үүсгэх виджетээ сонгоно уу"</string>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index 32c8c02..1770e89 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Sentuh & tahan untuk mengambil widget."</string>
- <string name="market" msgid="2619650989819296998">"Beli-belah"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Tidak dapat melepaskan item pada Skrin Utama."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pilih widget yang hendak dibuat"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 13d8843..6211361 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Trykk og hold inne for å plukke opp en modul."</string>
- <string name="market" msgid="2619650989819296998">"Butikk"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Kunne ikke slippe elementet på denne startsiden."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Velg modul for oppretting"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index c9f7e67..3e0f640 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"App is niet geïnstalleerd."</string>
<string name="activity_not_available" msgid="7456344436509528827">"App is niet beschikbaar"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Gedownloade app uitgeschakeld in veilige modus"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets uitgeschakeld in Veilige modus"</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">"Geheugen weergeven"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Blijf aanraken om een widget toe te voegen."</string>
- <string name="market" msgid="2619650989819296998">"Winkelen"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Kan item niet neerzetten in dit startscherm."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Widget selecteren om te maken"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 44e46e0..ee48b24 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplikacja nie jest zainstalowana."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplikacja niedostępna"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Pobrana aplikacja została wyłączona w trybie awaryjnym"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widżety są wyłączone w trybie bezpiecznym"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widżety"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widżety"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Pokaż pamięć"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Aby dodać widżet, kliknij go i przytrzymaj."</string>
- <string name="market" msgid="2619650989819296998">"Sklep"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Nie można upuścić elementu na tym ekranie głównym."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Wybierz widżet, który chcesz dodać"</string>
diff --git a/res/values-port/styles.xml b/res/values-port/styles.xml
deleted file mode 100644
index ab6a1eb..0000000
--- a/res/values-port/styles.xml
+++ /dev/null
@@ -1,25 +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.
-*/
--->
-
-<resources>
-<!-- AppsCustomize -->
- <style name="TabIndicator.AppsCustomize">
- <item name="android:maxWidth">130dp</item>
- </style>
-</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index fb33678..e19fcea 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"A aplicação não está instalada."</string>
<string name="activity_not_available" msgid="7456344436509528827">"A aplicação não está disponível"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicação transferida desativada no Modo de segurança"</string>
+ <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"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Prima sem soltar para escolher um widget."</string>
- <string name="market" msgid="2619650989819296998">"Comprar"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível largar o item neste Ecrã Principal."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Escolher um widget para criar"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 2f86d0b..355e71a 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Toque e pressione para selecionar um widget."</string>
- <string name="market" msgid="2619650989819296998">"Comprar"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Não foi possível soltar o item nesta tela inicial."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Selecione um widget para criar"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index c6000ee..a509399 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Aplicația nu este instalată."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Aplicația nu este disponibilă"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Aplicația descărcată este dezactivată în modul de siguranță"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgeturile sunt dezactivate în modul de siguranță"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgeturi"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgeturi"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Afișați memoria"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Atingeți lung un widget pentru a-l alege."</string>
- <string name="market" msgid="2619650989819296998">"Cumpărați"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Nu se poate plasa articolul pe ecranul de pornire."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Alegeți widgetul de creat"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 134582d..7cbd9fa 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Виджеты"</string>
<string name="widget_adder" msgid="3201040140710381657">"Виджеты"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Сведения о памяти"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Чтобы выбрать виджет, нажмите на значок и удерживайте его."</string>
- <string name="market" msgid="2619650989819296998">"Google Play"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Не удалось добавить элемент на главный экран"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Выберите виджет"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index d80b5ac..e3c242d 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Miniaplikáciu pridáte stlačením a podržaním."</string>
- <string name="market" msgid="2619650989819296998">"Obchod"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Položku sa nepodarilo presunúť na túto plochu."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Zvoľte miniaplikáciu na vytvorenie"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 882ddb4..807b1b4 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Za izbiro pripomočka se ga dotaknite in pridržite."</string>
- <string name="market" msgid="2619650989819296998">"Nakup"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Elementa ni mogoče spustiti na začetni zaslon."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Izberite pripomoček za ustvarjanje"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 63f48f5..3509252 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Виџети"</string>
<string name="widget_adder" msgid="3201040140710381657">"Виџети"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Прикажи меморију"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Додирните и задржите да бисте изабрали виџет."</string>
- <string name="market" msgid="2619650989819296998">"Купујте"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Није могуће отпустити ставку на почетни екран."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Избор виџета за прављење"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 674f1df..572309d 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Appen är inte installerad."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Appen är inte tillgänglig"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Den hämtade appen inaktiverades i säkert läge"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Widgets är inaktiverade i felsäkert läge"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Widgetar"</string>
<string name="widget_adder" msgid="3201040140710381657">"Widgetar"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Visa Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Tryck länge om du vill flytta en widget."</string>
- <string name="market" msgid="2619650989819296998">"Butik"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Objektet kunde inte släppas på startskärmen."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Ange vilken widget du vill använda"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 94f53ce..0284679 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Gusa na ushikilie ili kuteua wijeti."</string>
- <string name="market" msgid="2619650989819296998">"Nunua"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Haikuweza kudondosha kipengee kwenye skrini hii ya Kwanza."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chagua wijeti ili uunde"</string>
diff --git a/res/values-sw340dp-port/styles.xml b/res/values-sw340dp-port/styles.xml
index 24f4ba2..8ac3b5e 100644
--- a/res/values-sw340dp-port/styles.xml
+++ b/res/values-sw340dp-port/styles.xml
@@ -24,9 +24,4 @@
<item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
<item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
</style>
-
-<!-- AppsCustomize -->
- <style name="TabIndicator.AppsCustomize">
- <item name="android:maxWidth">150dp</item>
- </style>
</resources>
diff --git a/res/values-sw720dp-port/styles.xml b/res/values-sw720dp-port/styles.xml
deleted file mode 100644
index 57f07ac..0000000
--- a/res/values-sw720dp-port/styles.xml
+++ /dev/null
@@ -1,24 +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.
-*/
--->
-
-<resources>
- <style name="TabIndicator.AppsCustomize">
- <item name="android:maxWidth">180dp</item>
- </style>
-</resources>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index 71f0304..4ec04d9 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -19,13 +19,6 @@
<resources>
<!-- Workspace -->
- <style name="TabIndicator.AppsCustomize">
- <item name="android:paddingLeft">32dp</item>
- <item name="android:paddingRight">32dp</item>
- <item name="android:textSize">14sp</item>
- <item name="android:maxWidth">240dp</item>
- </style>
-
<style name="SearchButton">
</style>
<style name="DropTargetButtonContainer">
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 06ed6ec..bc9ddfb 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"วิดเจ็ต"</string>
<string name="widget_adder" msgid="3201040140710381657">"วิดเจ็ต"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"แสดง Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"แตะค้างเพื่อรับวิดเจ็ต"</string>
- <string name="market" msgid="2619650989819296998">"เลือกซื้อ"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"ไม่สามารถวางรายการลงในหน้าจอหลักนี้"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"เลือกวิดเจ็ตที่จะสร้าง"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 3c877d0..9078d15 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Hindi naka-install ang app."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Hindi available ang app"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Naka-disable ang na-download na app sa Safe mode"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Naka-disable ang mga widget sa Safe mode"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Mga Widget"</string>
<string name="widget_adder" msgid="3201040140710381657">"Mga Widget"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Ipakita ang Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Pindutin nang matagal upang kumuha ng widget."</string>
- <string name="market" msgid="2619650989819296998">"Mamili"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Hindi ma-drop ang item sa Home screen na ito."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Pumili ng widget na gagawin"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 2f67ad2..b71748e 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -26,11 +26,12 @@
<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="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>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Widget seçmek için dokunun ve basılı tutun."</string>
- <string name="market" msgid="2619650989819296998">"Mağaza"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Öğe bu Ana ekrana bırakılamadı."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Oluşturmak için widget seçin"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 12c9dd4..78cda53 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"Віджети"</string>
<string name="widget_adder" msgid="3201040140710381657">"Віджети"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Показати пам’ять"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Натисніть і утримуйте, щоб вибрати віджет."</string>
- <string name="market" msgid="2619650989819296998">"Магазин"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Не вдалося додати елемент на цей головний екран."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Вибрати віджет для створення"</string>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 79db2c5..61715c8 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Ứng dụng chưa được cài đặt."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Ứng dụng không có sẵn"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Ứng dụng đã tải xuống bị tắt ở chế độ An toàn"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Tiện ích con bị vô hiệu hóa ở chế độ an toàn"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Tiện ích con"</string>
<string name="widget_adder" msgid="3201040140710381657">"Tiện ích con"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Hiển thị bộ nhớ"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Chạm và giữ để chọn tiện ích con."</string>
- <string name="market" msgid="2619650989819296998">"Mua"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Không thể thả mục vào Màn hình chính này."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Chọn tiện ích con để tạo"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 37923dd..30e34b9 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -26,11 +26,12 @@
<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="widgets_tab_label" msgid="2921133187116603919">"小部件"</string>
<string name="widget_adder" msgid="3201040140710381657">"小部件"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"显示内存空间"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"触摸并按住小部件即可选择。"</string>
- <string name="market" msgid="2619650989819296998">"商店"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"无法将相关内容拖放到此主屏幕上。"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"选择要创建的小部件"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 346e60a..3656e2e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
<string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
- <string name="market" msgid="2619650989819296998">"商店"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至主畫面。"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index a63fb69..f9fdaa4 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -26,11 +26,11 @@
<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="widgets_tab_label" msgid="2921133187116603919">"小工具"</string>
<string name="widget_adder" msgid="3201040140710381657">"小工具"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"顯示記憶體"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"輕觸並按住小工具即可選取。"</string>
- <string name="market" msgid="2619650989819296998">"購物"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"無法將項目拖放至這個主螢幕上。"</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"選擇要建立的小工具"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index f94b166..79f8b54 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -26,11 +26,11 @@
<string name="activity_not_found" msgid="8071924732094499514">"Uhlelo lokusebenza alufakiwe."</string>
<string name="activity_not_available" msgid="7456344436509528827">"Uhlelo lokusebenza alutholakali"</string>
<string name="safemode_shortcut_error" msgid="9160126848219158407">"Uhlelo lokusebenza olulandiwe lukhutshaziwe kumodi ephephile"</string>
+ <string name="safemode_widget_error" msgid="4863470563535682004">"Amawijethi akhutshaziwe kwimodi yokuphepha"</string>
<string name="widgets_tab_label" msgid="2921133187116603919">"Amawijethi"</string>
<string name="widget_adder" msgid="3201040140710381657">"Amawijethi"</string>
<string name="toggle_weight_watcher" msgid="5645299835184636119">"Bonisa i-Mem"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"Thinta uphinde ubambe ukuze uphakamise iwijethi."</string>
- <string name="market" msgid="2619650989819296998">"Thenga"</string>
<string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
<string name="external_drop_widget_error" msgid="3165821058322217155">"Ayikwazanga ukwehlisela into kulesi sikrini se-Ikhaya."</string>
<string name="external_drop_widget_pick_title" msgid="3486317258037690630">"Khetha iwijethi ongayidala"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 65f8f22..b4e1543 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -130,12 +130,14 @@
<attr name="title" format="reference" />
<attr name="uri" format="string" />
</declare-styleable>
+
<declare-styleable name="Extra">
<attr name="key" format="string" />
<attr name="value" format="string" />
</declare-styleable>
<declare-styleable name="Include">
<attr name="workspace" format="reference" />
+ <attr name="folderItems" format="reference" />
</declare-styleable>
<declare-styleable name="PreloadIconDrawable">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 29837ea..2daf9fe 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -29,8 +29,6 @@
<color name="appwidget_error_color">#FCCC</color>
- <color name="workspace_all_apps_and_delete_zone_text_color">#CCFFFFFF</color>
- <color name="workspace_all_apps_and_delete_zone_text_shadow_color">#A0000000</color>
<color name="workspace_icon_text_color">#FFF</color>
<color name="quantum_panel_text_color">#FF666666</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dd9b170..a6397e3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -44,6 +44,8 @@
<string name="activity_not_available">App isn\'t available</string>
<!-- SafeMode shortcut error string -->
<string name="safemode_shortcut_error">Downloaded app disabled in Safe mode</string>
+ <!-- SafeMode widget error string -->
+ <string name="safemode_widget_error">Widgets disabled in Safe mode</string>
<!-- Labels for the tabs in the customize drawer -->
<string name="widgets_tab_label">Widgets</string>
@@ -54,9 +56,6 @@
<!-- AppsCustomize pane -->
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
<string name="long_press_widget_to_add">Touch & hold to pick up a widget.</string>
- <!-- Market button text. The market button text is removed in Launcher.java
- in the Phone UI. [CHAR LIMIT=32] -->
- <string name="market">Shop</string>
<!-- The format string for the dimensions of a widget in the drawer -->
<!-- There is a special version of this format string for Farsi -->
<string name="widget_dims_format">%1$d \u00d7 %2$d</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 56a205f..873b74c 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -78,35 +78,6 @@
<item name="android:shadowRadius">4.0</item>
</style>
- <style name="TabIndicator">
- <item name="android:layout_width">wrap_content</item>
- <item name="android:layout_height">match_parent</item>
- <item name="android:gravity">center</item>
- <item name="android:paddingLeft">20dp</item>
- <item name="android:paddingRight">20dp</item>
- <item name="android:background">@drawable/tab_widget_indicator_selector</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
- <item name="android:textSize">12sp</item>
- <item name="android:textStyle">bold</item>
- <item name="android:textAllCaps">true</item>
- <item name="android:singleLine">true</item>
- <item name="android:ellipsize">end</item>
- </style>
- <style name="TabIndicator.AppsCustomize">
- <!-- Overridden in values-land -->
- </style>
-
- <style name="MarketButton">
- <item name="android:paddingLeft">5dp</item>
- <item name="android:paddingRight">5dp</item>
- <item name="android:textColor">@color/workspace_all_apps_and_delete_zone_text_color</item>
- <item name="android:textSize">18sp</item>
- <item name="android:shadowColor">@color/workspace_all_apps_and_delete_zone_text_shadow_color</item>
- <item name="android:shadowDx">0.0</item>
- <item name="android:shadowDy">0.0</item>
- <item name="android:shadowRadius">2.0</item>
- </style>
-
<style name="PreloadIcon">
<item name="background">@drawable/virtual_preload</item>
<item name="indicatorSize">4dp</item>
diff --git a/res/xml/default_workspace_4x4_no_all_apps.xml b/res/xml/default_workspace_4x4_no_all_apps.xml
deleted file mode 100644
index 7e1301c..0000000
--- a/res/xml/default_workspace_4x4_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- Dialer Hangouts Maps Chrome Camera -->
- <favorite
- launcher:packageName="com.google.android.dialer"
- launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
- launcher:container="-101"
- launcher:screen="0"
- launcher:x="0"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.apps.maps"
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0"/>
- <favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.GoogleCamera"
- launcher:className="com.android.camera.CameraLauncher"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
-</favorites>
-
diff --git a/res/xml/default_workspace_5x5_no_all_apps.xml b/res/xml/default_workspace_5x5_no_all_apps.xml
deleted file mode 100644
index f54a204..0000000
--- a/res/xml/default_workspace_5x5_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- Dialer Hangouts Maps Chrome Camera -->
- <favorite
- launcher:packageName="com.google.android.dialer"
- launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.apps.maps"
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0"/>
- <favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.GoogleCamera"
- launcher:className="com.android.camera.CameraLauncher"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
-</favorites>
-
diff --git a/res/xml/default_workspace_5x6_no_all_apps.xml b/res/xml/default_workspace_5x6_no_all_apps.xml
deleted file mode 100644
index f54a204..0000000
--- a/res/xml/default_workspace_5x6_no_all_apps.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3">
- <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
- <!-- Dialer Hangouts Maps Chrome Camera -->
- <favorite
- launcher:packageName="com.google.android.dialer"
- launcher:className="com.google.android.dialer.extensions.GoogleDialtactsActivity"
- launcher:container="-101"
- launcher:screen="1"
- launcher:x="1"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.talk"
- launcher:className="com.google.android.talk.SigningInActivity"
- launcher:container="-101"
- launcher:screen="2"
- launcher:x="2"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.apps.maps"
- launcher:className="com.google.android.maps.MapsActivity"
- launcher:container="-101"
- launcher:screen="3"
- launcher:x="3"
- launcher:y="0"/>
- <favorite
- launcher:packageName="com.android.chrome"
- launcher:className="com.google.android.apps.chrome.Main"
- launcher:container="-101"
- launcher:screen="4"
- launcher:x="4"
- launcher:y="0" />
- <favorite
- launcher:packageName="com.google.android.GoogleCamera"
- launcher:className="com.android.camera.CameraLauncher"
- launcher:container="-101"
- launcher:screen="5"
- launcher:x="5"
- launcher:y="0" />
-</favorites>
-
diff --git a/src/com/android/launcher3/AccessibleTabView.java b/src/com/android/launcher3/AccessibleTabView.java
deleted file mode 100644
index 90a7865..0000000
--- a/src/com/android/launcher3/AccessibleTabView.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.TextView;
-
-/**
- * We use a custom tab view to process our own focus traversals.
- */
-public class AccessibleTabView extends TextView {
- public AccessibleTabView(Context context) {
- super(context);
- }
-
- public AccessibleTabView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public AccessibleTabView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return FocusHelper.handleTabKeyEvent(this, keyCode, event)
- || super.onKeyDown(keyCode, event);
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return FocusHelper.handleTabKeyEvent(this, keyCode, event)
- || super.onKeyUp(keyCode, event);
- }
-}
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 1bd2907..7f3b7fb 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -728,7 +728,8 @@
!(target instanceof DeleteDropTarget) && !(target instanceof Folder))) {
// Exit spring loaded mode if we have not successfully dropped or have not handled the
// drop in Workspace
- mLauncher.exitSpringLoadedDragMode();
+ mLauncher.exitSpringLoadedDragModeDelayed(true,
+ Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
mLauncher.unlockScreenOrientation(false);
} else {
mLauncher.unlockScreenOrientation(false);
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index 08ed89b..a5d2228 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -36,7 +36,6 @@
import android.util.Patterns;
import com.android.launcher3.LauncherProvider.SqlArguments;
-import com.android.launcher3.LauncherProvider.WorkspaceLoader;
import com.android.launcher3.LauncherSettings.Favorites;
import org.xmlpull.v1.XmlPullParser;
@@ -47,13 +46,11 @@
import java.util.HashMap;
/**
- * This class contains contains duplication of functionality as found in
- * LauncherProvider#DatabaseHelper. It has been isolated and differentiated in order
- * to cleanly and separately represent AutoInstall default layout format and policy.
+ * Layout parsing code for auto installs layout
*/
-public class AutoInstallsLayout implements WorkspaceLoader {
+public class AutoInstallsLayout {
private static final String TAG = "AutoInstalls";
- private static final boolean LOGD = true;
+ private static final boolean LOGD = false;
/** Marker action used to discover a package which defines launcher customization */
static final String ACTION_LAUNCHER_CUSTOMIZATION =
@@ -76,7 +73,8 @@
Log.e(TAG, "Layout definition not found in package: " + pkg);
return null;
}
- return new AutoInstallsLayout(context, appWidgetHost, callback, pkg, res, layoutId);
+ return new AutoInstallsLayout(context, appWidgetHost, callback, res, layoutId,
+ TAG_WORKSPACE);
}
// Object Tags
@@ -116,45 +114,55 @@
private final AppWidgetHost mAppWidgetHost;
private final LayoutParserCallback mCallback;
- private final PackageManager mPackageManager;
+ protected final PackageManager mPackageManager;
+ protected final Resources mSourceRes;
+ protected final int mLayoutId;
+
+ private final int mHotseatAllAppsRank;
+
+ private final long[] mTemp = new long[2];
private final ContentValues mValues;
+ private final String mRootTag;
- private final Resources mRes;
- private final int mLayoutId;
-
- private SQLiteDatabase mDb;
+ protected SQLiteDatabase mDb;
public AutoInstallsLayout(Context context, AppWidgetHost appWidgetHost,
- LayoutParserCallback callback, String packageName, Resources res, int layoutId) {
+ LayoutParserCallback callback, Resources res,
+ int layoutId, String rootTag) {
mContext = context;
mAppWidgetHost = appWidgetHost;
mCallback = callback;
mPackageManager = context.getPackageManager();
mValues = new ContentValues();
+ mRootTag = rootTag;
- mRes = res;
+ mSourceRes = res;
mLayoutId = layoutId;
+ mHotseatAllAppsRank = LauncherAppState.getInstance()
+ .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
}
- @Override
+ /**
+ * Loads the layout in the db and returns the number of entries added on the desktop.
+ */
public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
mDb = db;
try {
- return parseLayout(mRes, mLayoutId, screenIds);
+ return parseLayout(mLayoutId, screenIds);
} catch (Exception e) {
Log.w(TAG, "Got exception parsing layout.", e);
return -1;
}
}
- private int parseLayout(Resources res, int layoutId, ArrayList<Long> screenIds)
+ /**
+ * Parses the layout and returns the number of elements added on the homescreen.
+ */
+ protected int parseLayout(int layoutId, ArrayList<Long> screenIds)
throws XmlPullParserException, IOException {
- final int hotseatAllAppsRank = LauncherAppState.getInstance()
- .getDynamicGrid().getDeviceProfile().hotseatAllAppsRank;
-
- XmlResourceParser parser = res.getXml(layoutId);
- beginDocument(parser, TAG_WORKSPACE);
+ XmlResourceParser parser = mSourceRes.getXml(layoutId);
+ beginDocument(parser, mRootTag);
final int depth = parser.getDepth();
int type;
HashMap<String, TagParser> tagParserMap = getLayoutElementsMap();
@@ -165,47 +173,62 @@
if (type != XmlPullParser.START_TAG) {
continue;
}
-
- mValues.clear();
- final int container;
- final long screenId;
-
- if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) {
- container = Favorites.CONTAINER_HOTSEAT;
-
- // Hack: hotseat items are stored using screen ids
- long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK));
- screenId = (rank < hotseatAllAppsRank) ? rank : (rank + 1);
-
- } else {
- container = Favorites.CONTAINER_DESKTOP;
- screenId = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
-
- mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
- mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
- }
-
- mValues.put(Favorites.CONTAINER, container);
- mValues.put(Favorites.SCREEN, screenId);
-
- TagParser tagParser = tagParserMap.get(parser.getName());
- if (tagParser == null) {
- if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
- continue;
- }
- long newElementId = tagParser.parseAndAdd(parser, res);
- if (newElementId >= 0) {
- // Keep track of the set of screens which need to be added to the db.
- if (!screenIds.contains(screenId) &&
- container == Favorites.CONTAINER_DESKTOP) {
- screenIds.add(screenId);
- }
- count++;
- }
+ count += parseAndAddNode(parser, tagParserMap, screenIds);
}
return count;
}
+ /**
+ * Parses container and screenId attribute from the current tag, and puts it in the out.
+ * @param out array of size 2.
+ */
+ protected void parseContainerAndScreen(XmlResourceParser parser, long[] out) {
+ if (HOTSEAT_CONTAINER_NAME.equals(getAttributeValue(parser, ATTR_CONTAINER))) {
+ out[0] = Favorites.CONTAINER_HOTSEAT;
+ // Hack: hotseat items are stored using screen ids
+ long rank = Long.parseLong(getAttributeValue(parser, ATTR_RANK));
+ out[1] = (rank < mHotseatAllAppsRank) ? rank : (rank + 1);
+ } else {
+ out[0] = Favorites.CONTAINER_DESKTOP;
+ out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
+ }
+ }
+
+ /**
+ * Parses the current node and returns the number of elements added.
+ */
+ protected int parseAndAddNode(
+ XmlResourceParser parser,
+ HashMap<String, TagParser> tagParserMap,
+ ArrayList<Long> screenIds)
+ throws XmlPullParserException, IOException {
+ mValues.clear();
+ parseContainerAndScreen(parser, mTemp);
+ final long container = mTemp[0];
+ final long screenId = mTemp[1];
+
+ mValues.put(Favorites.CONTAINER, container);
+ mValues.put(Favorites.SCREEN, screenId);
+ mValues.put(Favorites.CELLX, getAttributeValue(parser, ATTR_X));
+ mValues.put(Favorites.CELLY, getAttributeValue(parser, ATTR_Y));
+
+ TagParser tagParser = tagParserMap.get(parser.getName());
+ if (tagParser == null) {
+ if (LOGD) Log.d(TAG, "Ignoring unknown element tag: " + parser.getName());
+ return 0;
+ }
+ long newElementId = tagParser.parseAndAdd(parser);
+ if (newElementId >= 0) {
+ // Keep track of the set of screens which need to be added to the db.
+ if (!screenIds.contains(screenId) &&
+ container == Favorites.CONTAINER_DESKTOP) {
+ screenIds.add(screenId);
+ }
+ return 1;
+ }
+ return 0;
+ }
+
protected long addShortcut(String title, Intent intent, int type) {
long id = mCallback.generateNewItemId();
mValues.put(Favorites.INTENT, intent.toUri(0));
@@ -225,7 +248,7 @@
HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
parsers.put(TAG_APP_ICON, new AppShortcutParser());
parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
- parsers.put(TAG_SHORTCUT, new ShortcutParser());
+ parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
return parsers;
}
@@ -235,23 +258,26 @@
parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
parsers.put(TAG_FOLDER, new FolderParser());
parsers.put(TAG_APPWIDGET, new AppWidgetParser());
- parsers.put(TAG_SHORTCUT, new ShortcutParser());
+ parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
return parsers;
}
- private interface TagParser {
+ protected interface TagParser {
/**
* Parses the tag and adds to the db
* @return the id of the row added or -1;
*/
- long parseAndAdd(XmlResourceParser parser, Resources res)
+ long parseAndAdd(XmlResourceParser parser)
throws XmlPullParserException, IOException;
}
- private class AppShortcutParser implements TagParser {
+ /**
+ * App shortcuts: required attributes packageName and className
+ */
+ protected class AppShortcutParser implements TagParser {
@Override
- public long parseAndAdd(XmlResourceParser parser, Resources res) {
+ public long parseAndAdd(XmlResourceParser parser) {
final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
@@ -277,20 +303,30 @@
return addShortcut(info.loadLabel(mPackageManager).toString(),
intent, Favorites.ITEM_TYPE_APPLICATION);
} catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Unable to add favorite: " + packageName + "/" + className, e);
+ if (LOGD) Log.w(TAG, "Unable to add favorite: " + packageName + "/" + className, e);
}
return -1;
} else {
- if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component or uri");
- return -1;
+ return invalidPackageOrClass(parser);
}
}
+
+ /**
+ * Helper method to allow extending the parser capabilities
+ */
+ protected long invalidPackageOrClass(XmlResourceParser parser) {
+ if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component");
+ return -1;
+ }
}
- private class AutoInstallParser implements TagParser {
+ /**
+ * AutoInstall: required attributes packageName and className
+ */
+ protected class AutoInstallParser implements TagParser {
@Override
- public long parseAndAdd(XmlResourceParser parser, Resources res) {
+ public long parseAndAdd(XmlResourceParser parser) {
final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
@@ -309,11 +345,19 @@
}
}
- private class ShortcutParser implements TagParser {
+ /**
+ * Parses a web shortcut. Required attributes url, icon, title
+ */
+ protected class ShortcutParser implements TagParser {
+
+ private final Resources mIconRes;
+
+ public ShortcutParser(Resources iconRes) {
+ mIconRes = iconRes;
+ }
@Override
- public long parseAndAdd(XmlResourceParser parser, Resources res) {
- final String url = getAttributeValue(parser, ATTR_URL);
+ public long parseAndAdd(XmlResourceParser parser) {
final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0);
@@ -322,29 +366,46 @@
return -1;
}
- if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
- if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
+ final Intent intent = parseIntent(parser);
+ if (intent == null) {
return -1;
}
- Drawable icon = res.getDrawable(iconId);
+
+ Drawable icon = mIconRes.getDrawable(iconId);
if (icon == null) {
if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon");
return -1;
}
ItemInfo.writeBitmap(mValues, Utilities.createIconBitmap(icon, mContext));
- final Intent intent = new Intent(Intent.ACTION_VIEW, null)
- .setData(Uri.parse(url))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ mValues.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
+ mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
+ mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
+
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- return addShortcut(res.getString(titleResId), intent, Favorites.ITEM_TYPE_SHORTCUT);
+ return addShortcut(mSourceRes.getString(titleResId),
+ intent, Favorites.ITEM_TYPE_SHORTCUT);
+ }
+
+ protected Intent parseIntent(XmlResourceParser parser) {
+ final String url = getAttributeValue(parser, ATTR_URL);
+ if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
+ if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
+ return null;
+ }
+ return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url));
}
}
- private class AppWidgetParser implements TagParser {
+ /**
+ * AppWidget parser: Required attributes packageName, className, spanX and spanY.
+ * Options child nodes: <extra key=... value=... />
+ */
+ protected class AppWidgetParser implements TagParser {
@Override
- public long parseAndAdd(XmlResourceParser parser, Resources res)
+ public long parseAndAdd(XmlResourceParser parser)
throws XmlPullParserException, IOException {
final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
@@ -429,16 +490,24 @@
}
}
- private class FolderParser implements TagParser {
- private final HashMap<String, TagParser> mFolderElements = getFolderElementsMap();
+ protected class FolderParser implements TagParser {
+ private final HashMap<String, TagParser> mFolderElements;
+
+ public FolderParser() {
+ this(getFolderElementsMap());
+ }
+
+ public FolderParser(HashMap<String, TagParser> elements) {
+ mFolderElements = elements;
+ }
@Override
- public long parseAndAdd(XmlResourceParser parser, Resources res)
+ public long parseAndAdd(XmlResourceParser parser)
throws XmlPullParserException, IOException {
final String title;
final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
if (titleResId != 0) {
- title = res.getString(titleResId);
+ title = mSourceRes.getString(titleResId);
} else {
title = mContext.getResources().getString(R.string.folder_name);
}
@@ -469,7 +538,7 @@
TagParser tagParser = mFolderElements.get(parser.getName());
if (tagParser != null) {
- final long id = tagParser.parseAndAdd(parser, res);
+ final long id = tagParser.parseAndAdd(parser);
if (id >= 0) {
folderItems.add(id);
}
@@ -508,7 +577,7 @@
}
}
- private static final void beginDocument(XmlPullParser parser, String firstElementName)
+ protected static final void beginDocument(XmlPullParser parser, String firstElementName)
throws XmlPullParserException, IOException {
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
@@ -528,7 +597,7 @@
* Return attribute value, attempting launcher-specific namespace first
* before falling back to anonymous attribute.
*/
- private static String getAttributeValue(XmlResourceParser parser, String attribute) {
+ protected static String getAttributeValue(XmlResourceParser parser, String attribute) {
String value = parser.getAttributeValue(
"http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
if (value == null) {
@@ -541,7 +610,7 @@
* Return attribute resource value, attempting launcher-specific namespace
* first before falling back to anonymous attribute.
*/
- private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
+ protected static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
int defaultValue) {
int value = parser.getAttributeResourceValue(
"http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
diff --git a/src/com/android/launcher3/DefaultLayoutParser.java b/src/com/android/launcher3/DefaultLayoutParser.java
new file mode 100644
index 0000000..e3ea40e
--- /dev/null
+++ b/src/com/android/launcher3/DefaultLayoutParser.java
@@ -0,0 +1,290 @@
+package com.android.launcher3;
+
+import android.appwidget.AppWidgetHost;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.launcher3.LauncherSettings.Favorites;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Implements the layout parser with rules for internal layouts and partner layouts.
+ */
+public class DefaultLayoutParser extends AutoInstallsLayout {
+ private static final String TAG = "DefaultLayoutParser";
+
+ private static final String TAG_RESOLVE = "resolve";
+ private static final String TAG_FAVORITES = "favorites";
+ private static final String TAG_FAVORITE = "favorite";
+ private static final String TAG_APPWIDGET = "appwidget";
+ private static final String TAG_SHORTCUT = "shortcut";
+ private static final String TAG_FOLDER = "folder";
+ private static final String TAG_PARTNER_FOLDER = "partner-folder";
+ private static final String TAG_INCLUDE = "include";
+
+ private static final String ATTR_URI = "uri";
+ private static final String ATTR_WORKSPACE = "workspace";
+ private static final String ATTR_CONTAINER = "container";
+ private static final String ATTR_SCREEN = "screen";
+ private static final String ATTR_FOLDER_ITEMS = "folderItems";
+
+ public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
+ LayoutParserCallback callback, Resources sourceRes, int layoutId) {
+ super(context, appWidgetHost, callback, sourceRes, layoutId, TAG_FAVORITES);
+ Log.e(TAG, "Default layout parser initialized");
+ }
+
+ @Override
+ protected HashMap<String, TagParser> getFolderElementsMap() {
+ return getFolderElementsMap(mSourceRes);
+ }
+
+ private HashMap<String, TagParser> getFolderElementsMap(Resources res) {
+ HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+ parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
+ parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
+ return parsers;
+ }
+
+ @Override
+ protected HashMap<String, TagParser> getLayoutElementsMap() {
+ HashMap<String, TagParser> parsers = new HashMap<String, TagParser>();
+ parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
+ parsers.put(TAG_APPWIDGET, new AppWidgetParser());
+ parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
+ parsers.put(TAG_RESOLVE, new ResolveParser());
+ parsers.put(TAG_FOLDER, new MyFolderParser());
+ parsers.put(TAG_PARTNER_FOLDER, new PartnerFolderParser());
+ return parsers;
+ }
+
+ @Override
+ protected void parseContainerAndScreen(XmlResourceParser parser, long[] out) {
+ out[0] = LauncherSettings.Favorites.CONTAINER_DESKTOP;
+ String strContainer = getAttributeValue(parser, ATTR_CONTAINER);
+ if (strContainer != null) {
+ out[0] = Long.valueOf(strContainer);
+ }
+ out[1] = Long.parseLong(getAttributeValue(parser, ATTR_SCREEN));
+ }
+
+ @Override
+ protected int parseAndAddNode(
+ XmlResourceParser parser,
+ HashMap<String, TagParser> tagParserMap,
+ ArrayList<Long> screenIds)
+ throws XmlPullParserException, IOException {
+ if (TAG_INCLUDE.equals(parser.getName())) {
+ final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
+ if (resId != 0) {
+ // recursively load some more favorites, why not?
+ return parseLayout(resId, screenIds);
+ } else {
+ return 0;
+ }
+ } else {
+ return super.parseAndAddNode(parser, tagParserMap, screenIds);
+ }
+ }
+
+ /**
+ * AppShortcutParser which also supports adding URI based intents
+ */
+ private class AppShortcutWithUriParser extends AppShortcutParser {
+
+ @Override
+ protected long invalidPackageOrClass(XmlResourceParser parser) {
+ final String uri = getAttributeValue(parser, ATTR_URI);
+ if (TextUtils.isEmpty(uri)) {
+ Log.e(TAG, "Skipping invalid <favorite> with no component or uri");
+ return -1;
+ }
+
+ final Intent metaIntent;
+ try {
+ metaIntent = Intent.parseUri(uri, 0);
+ } catch (URISyntaxException e) {
+ Log.e(TAG, "Unable to add meta-favorite: " + uri, e);
+ return -1;
+ }
+
+ ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ final List<ResolveInfo> appList = mPackageManager.queryIntentActivities(
+ metaIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ // Verify that the result is an app and not just the resolver dialog asking which
+ // app to use.
+ if (wouldLaunchResolverActivity(resolved, appList)) {
+ // If only one of the results is a system app then choose that as the default.
+ final ResolveInfo systemApp = getSingleSystemActivity(appList);
+ if (systemApp == null) {
+ // There is no logical choice for this meta-favorite, so rather than making
+ // a bad choice just add nothing.
+ Log.w(TAG, "No preference or single system activity found for "
+ + metaIntent.toString());
+ return -1;
+ }
+ resolved = systemApp;
+ }
+ final ActivityInfo info = resolved.activityInfo;
+ final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName);
+ if (intent == null) {
+ return -1;
+ }
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+
+ return addShortcut(info.loadLabel(mPackageManager).toString(), intent,
+ Favorites.ITEM_TYPE_APPLICATION);
+ }
+
+ private ResolveInfo getSingleSystemActivity(List<ResolveInfo> appList) {
+ ResolveInfo systemResolve = null;
+ final int N = appList.size();
+ for (int i = 0; i < N; ++i) {
+ try {
+ ApplicationInfo info = mPackageManager.getApplicationInfo(
+ appList.get(i).activityInfo.packageName, 0);
+ if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if (systemResolve != null) {
+ return null;
+ } else {
+ systemResolve = appList.get(i);
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Unable to get info about resolve results", e);
+ return null;
+ }
+ }
+ return systemResolve;
+ }
+
+ private boolean wouldLaunchResolverActivity(ResolveInfo resolved,
+ List<ResolveInfo> appList) {
+ // If the list contains the above resolved activity, then it can't be
+ // ResolverActivity itself.
+ for (int i = 0; i < appList.size(); ++i) {
+ ResolveInfo tmp = appList.get(i);
+ if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
+ && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+
+ /**
+ * Shortcut parser which allows any uri and not just web urls.
+ */
+ private class UriShortcutParser extends ShortcutParser {
+
+ public UriShortcutParser(Resources iconRes) {
+ super(iconRes);
+ }
+
+ @Override
+ protected Intent parseIntent(XmlResourceParser parser) {
+ String uri = null;
+ try {
+ uri = getAttributeValue(parser, ATTR_URI);
+ return Intent.parseUri(uri, 0);
+ } catch (URISyntaxException e) {
+ Log.w(TAG, "Shortcut has malformed uri: " + uri);
+ return null; // Oh well
+ }
+ }
+ }
+
+ /**
+ * Contains a list of <favorite> nodes, and accepts the first successfully parsed node.
+ */
+ private class ResolveParser implements TagParser {
+
+ private final AppShortcutWithUriParser mChildParser = new AppShortcutWithUriParser();
+
+ @Override
+ public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+ IOException {
+ final int groupDepth = parser.getDepth();
+ int type;
+ long addedId = -1;
+ while ((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > groupDepth) {
+ if (type != XmlPullParser.START_TAG || addedId > -1) {
+ continue;
+ }
+ final String fallback_item_name = parser.getName();
+ if (TAG_FAVORITE.equals(fallback_item_name)) {
+ addedId = mChildParser.parseAndAdd(parser);
+ } else {
+ Log.e(TAG, "Fallback groups can contain only favorites, found "
+ + fallback_item_name);
+ }
+ }
+ return addedId;
+ }
+ }
+
+ /**
+ * A parser which adds a folder whose contents come from partner apk.
+ */
+ private class PartnerFolderParser implements TagParser {
+
+ @Override
+ public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+ IOException {
+ // Folder contents come from an external XML resource
+ final Partner partner = Partner.get(mPackageManager);
+ if (partner != null) {
+ final Resources partnerRes = partner.getResources();
+ final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
+ "xml", partner.getPackageName());
+ if (resId != 0) {
+ final XmlResourceParser partnerParser = partnerRes.getXml(resId);
+ beginDocument(partnerParser, TAG_FOLDER);
+
+ FolderParser folderParser = new FolderParser(getFolderElementsMap(partnerRes));
+ return folderParser.parseAndAdd(partnerParser);
+ }
+ }
+ return -1;
+ }
+ }
+
+ /**
+ * An extension of FolderParser which allows adding items from a different xml.
+ */
+ private class MyFolderParser extends FolderParser {
+
+ @Override
+ public long parseAndAdd(XmlResourceParser parser) throws XmlPullParserException,
+ IOException {
+ final int resId = getAttributeResourceValue(parser, ATTR_FOLDER_ITEMS, 0);
+ if (resId != 0) {
+ parser = mSourceRes.getXml(resId);
+ beginDocument(parser, TAG_FOLDER);
+ }
+ return super.parseAndAdd(parser);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 05e8906..ea058ea 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -21,8 +21,6 @@
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ResolveInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -41,12 +39,8 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
-import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
-import java.util.List;
-import java.util.Set;
-
public class DeleteDropTarget extends ButtonDropTarget {
private static int DELETE_ANIMATION_DURATION = 285;
private static int FLING_DELETE_ANIMATION_DURATION = 350;
@@ -266,7 +260,7 @@
public void run() {
completeDrop(d);
mSearchDropTargetBar.onDragEnd();
- mLauncher.exitSpringLoadedDragMode();
+ mLauncher.exitSpringLoadedDragModeDelayed(true, 0, null);
}
};
dragLayer.animateView(d.dragView, from, to, scale, 1f, 1f, 0.1f, 0.1f,
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index daf5556..b2366bb 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -75,7 +75,6 @@
private float hotseatIconSize;
int defaultLayoutId;
- int defaultNoAllAppsLayoutId;
boolean isLandscape;
boolean isTablet;
@@ -136,7 +135,7 @@
private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
DeviceProfile(String n, float w, float h, float r, float c,
- float is, float its, float hs, float his, int dlId, int dnalId) {
+ float is, float its, float hs, float his, int dlId) {
// Ensure that we have an odd number of hotseat items (since we need to place all apps)
if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
@@ -152,7 +151,6 @@
numHotseatIcons = hs;
hotseatIconSize = his;
defaultLayoutId = dlId;
- defaultNoAllAppsLayoutId = dnalId;
}
DeviceProfile() {
@@ -215,9 +213,6 @@
// Snap to the closest default layout id
defaultLayoutId = closestProfile.defaultLayoutId;
- // Snap to the closest default no all-apps layout id
- defaultNoAllAppsLayoutId = closestProfile.defaultNoAllAppsLayoutId;
-
// Interpolate the icon size
points.clear();
for (DeviceProfile p : profiles) {
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index 6d0a2be..480dce9 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -26,10 +26,16 @@
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
-import android.view.*;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList;
+import java.util.HashSet;
/**
* Class for initiating a drag within a view or across multiple views.
@@ -318,18 +324,17 @@
}
endDrag();
}
- public void onAppsRemoved(final ArrayList<String> packageNames, ArrayList<AppInfo> appInfos) {
+ public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) {
// Cancel the current drag if we are removing an app that we are dragging
if (mDragObject != null) {
Object rawDragInfo = mDragObject.dragInfo;
if (rawDragInfo instanceof ShortcutInfo) {
ShortcutInfo dragInfo = (ShortcutInfo) rawDragInfo;
- for (AppInfo info : appInfos) {
+ for (ComponentName componentName : cns) {
// Added null checks to prevent NPE we've seen in the wild
- if (dragInfo != null &&
- dragInfo.intent != null && info != null) {
+ if (dragInfo != null && dragInfo.intent != null) {
ComponentName cn = dragInfo.intent.getComponent();
- boolean isSameComponent = cn != null && (cn.equals(info.componentName) ||
+ boolean isSameComponent = cn != null && (cn.equals(componentName) ||
packageNames.contains(cn.getPackageName()));
if (isSameComponent) {
cancelDrag();
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index a8a61ea..ff9072a 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -89,6 +89,8 @@
private Drawable mLeftHoverDrawableActive;
private Drawable mRightHoverDrawableActive;
+ private boolean mBlockTouches = false;
+
/**
* Used to create a new DragLayer from XML.
*
@@ -185,11 +187,19 @@
return false;
}
+ public void setBlockTouch(boolean block) {
+ mBlockTouches = block;
+ }
+
private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
Rect hitRect = new Rect();
int x = (int) ev.getX();
int y = (int) ev.getY();
+ if (mBlockTouches) {
+ return true;
+ }
+
for (AppWidgetResizeFrame child: mResizeFrames) {
child.getHitRect(hitRect);
if (hitRect.contains(x, y)) {
@@ -332,6 +342,10 @@
int x = (int) ev.getX();
int y = (int) ev.getY();
+ if (mBlockTouches) {
+ return true;
+ }
+
if (action == MotionEvent.ACTION_DOWN) {
if (handleTouchDown(ev, false)) {
return true;
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 94a07d7..aa08148 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -60,41 +60,30 @@
DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
// Our phone profiles include the bar sizes in each orientation
deviceProfiles.add(new DeviceProfile("Super Short Stubby",
- 255, 300, 2, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 255, 300, 2, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Shorter Stubby",
- 255, 400, 3, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 255, 400, 3, 3, 48, 13, (hasAA ? 3 : 5), 48, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Short Stubby",
- 275, 420, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 275, 420, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Stubby",
- 255, 450, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 255, 450, 3, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Nexus S",
- 296, 491.33f, 4, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 296, 491.33f, 4, 4, 48, 13, (hasAA ? 5 : 5), 48, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Nexus 4",
- 335, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 335, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Nexus 5",
- 359, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 359, 567, 4, 4, DEFAULT_ICON_SIZE_DP, 13, (hasAA ? 5 : 5), 56, R.xml.default_workspace_4x4));
deviceProfiles.add(new DeviceProfile("Large Phone",
- 406, 694, 5, 5, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5,
- R.xml.default_workspace_5x5_no_all_apps));
+ 406, 694, 5, 5, 64, 14.4f, 5, 56, R.xml.default_workspace_5x5));
// The tablet profile is odd in that the landscape orientation
// also includes the nav bar on the side
deviceProfiles.add(new DeviceProfile("Nexus 7",
- 575, 904, 5, 6, 72, 14.4f, 7, 60, R.xml.default_workspace_5x6,
- R.xml.default_workspace_5x6_no_all_apps));
+ 575, 904, 5, 6, 72, 14.4f, 7, 60, R.xml.default_workspace_5x6));
// Larger tablet profiles always have system bars on the top & bottom
deviceProfiles.add(new DeviceProfile("Nexus 10",
- 727, 1207, 5, 6, 76, 14.4f, 7, 64, R.xml.default_workspace_5x6,
- R.xml.default_workspace_5x6_no_all_apps));
+ 727, 1207, 5, 6, 76, 14.4f, 7, 64, R.xml.default_workspace_5x6));
deviceProfiles.add(new DeviceProfile("20-inch Tablet",
- 1527, 2527, 7, 7, 100, 20, 7, 72, R.xml.default_workspace_4x4,
- R.xml.default_workspace_4x4_no_all_apps));
+ 1527, 2527, 7, 7, 100, 20, 7, 72, R.xml.default_workspace_4x4));
mMinWidth = dpiFromPx(minWidthPx, dm);
mMinHeight = dpiFromPx(minHeightPx, dm);
mProfile = new DeviceProfile(context, deviceProfiles,
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index d529b39..e607047 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -17,12 +17,10 @@
package com.android.launcher3;
import android.content.res.Configuration;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.ScrollView;
import java.util.ArrayList;
@@ -58,16 +56,6 @@
}
public class FocusHelper {
- /**
- * Private helper to get the parent TabHost in the view hiearchy.
- */
- private static AppsCustomizeTabHost findTabHostParent(View v) {
- ViewParent p = v.getParent();
- while (p != null && !(p instanceof AppsCustomizeTabHost)) {
- p = p.getParent();
- }
- return (AppsCustomizeTabHost) p;
- }
/**
* Returns the Viewgroup containing page contents for the page at the index specified.
@@ -82,148 +70,6 @@
}
/**
- * Handles key events in a PageViewExtendedLayout containing PagedViewWidgets.
- */
- static boolean handlePagedViewGridLayoutWidgetKeyEvent(PagedViewWidget w, int keyCode,
- KeyEvent e) {
-
- final PagedViewGridLayout parent = (PagedViewGridLayout) w.getParent();
- final PagedView container = (PagedView) parent.getParent();
- final int widgetIndex = parent.indexOfChild(w);
- final int widgetCount = parent.getChildCount();
- final int pageIndex = ((PagedView) container).indexToPage(container.indexOfChild(parent));
- final int pageCount = container.getChildCount();
- final int cellCountX = parent.getCellCountX();
- final int cellCountY = parent.getCellCountY();
- final int x = widgetIndex % cellCountX;
- final int y = widgetIndex / cellCountX;
-
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- ViewGroup newParent = null;
- // Now that we load items in the bg asynchronously, we can't just focus
- // child siblings willy-nilly
- View child = null;
- boolean wasHandled = false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- // Select the previous widget or the last widget on the previous page
- if (widgetIndex > 0) {
- parent.getChildAt(widgetIndex - 1).requestFocus();
- } else {
- if (pageIndex > 0) {
- newParent = getAppsCustomizePage(container, pageIndex - 1);
- if (newParent != null) {
- child = newParent.getChildAt(newParent.getChildCount() - 1);
- if (child != null) child.requestFocus();
- }
- }
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- // Select the next widget or the first widget on the next page
- if (widgetIndex < (widgetCount - 1)) {
- parent.getChildAt(widgetIndex + 1).requestFocus();
- } else {
- if (pageIndex < (pageCount - 1)) {
- newParent = getAppsCustomizePage(container, pageIndex + 1);
- if (newParent != null) {
- child = newParent.getChildAt(0);
- if (child != null) child.requestFocus();
- }
- }
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- if (handleKeyEvent) {
- // Select the closest icon in the previous row, otherwise select the tab bar
- if (y > 0) {
- int newWidgetIndex = ((y - 1) * cellCountX) + x;
- child = parent.getChildAt(newWidgetIndex);
- if (child != null) child.requestFocus();
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (handleKeyEvent) {
- // Select the closest icon in the previous row, otherwise do nothing
- if (y < (cellCountY - 1)) {
- int newWidgetIndex = Math.min(widgetCount - 1, ((y + 1) * cellCountX) + x);
- child = parent.getChildAt(newWidgetIndex);
- if (child != null) child.requestFocus();
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_ENTER:
- case KeyEvent.KEYCODE_DPAD_CENTER:
- if (handleKeyEvent) {
- // Simulate a click on the widget
- View.OnClickListener clickListener = (View.OnClickListener) container;
- clickListener.onClick(w);
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_PAGE_UP:
- if (handleKeyEvent) {
- // Select the first item on the previous page, or the first item on this page
- // if there is no previous page
- if (pageIndex > 0) {
- newParent = getAppsCustomizePage(container, pageIndex - 1);
- if (newParent != null) {
- child = newParent.getChildAt(0);
- }
- } else {
- child = parent.getChildAt(0);
- }
- if (child != null) child.requestFocus();
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_PAGE_DOWN:
- if (handleKeyEvent) {
- // Select the first item on the next page, or the last item on this page
- // if there is no next page
- if (pageIndex < (pageCount - 1)) {
- newParent = getAppsCustomizePage(container, pageIndex + 1);
- if (newParent != null) {
- child = newParent.getChildAt(0);
- }
- } else {
- child = parent.getChildAt(widgetCount - 1);
- }
- if (child != null) child.requestFocus();
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_MOVE_HOME:
- if (handleKeyEvent) {
- // Select the first item on this page
- child = parent.getChildAt(0);
- if (child != null) child.requestFocus();
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_MOVE_END:
- if (handleKeyEvent) {
- // Select the last item on this page
- parent.getChildAt(widgetCount - 1).requestFocus();
- }
- wasHandled = true;
- break;
- default: break;
- }
- return wasHandled;
- }
-
- /**
* Handles key events in a PageViewCellLayout containing PagedViewIcons.
*/
static boolean handleAppsCustomizeKeyEvent(View v, int keyCode, KeyEvent e) {
@@ -394,60 +240,6 @@
}
/**
- * Handles key events in the tab widget.
- */
- static boolean handleTabKeyEvent(AccessibleTabView v, int keyCode, KeyEvent e) {
- if (!LauncherAppState.getInstance().isScreenLarge()) return false;
-
- final FocusOnlyTabWidget parent = (FocusOnlyTabWidget) v.getParent();
- final AppsCustomizeTabHost tabHost = findTabHostParent(parent);
- final ViewGroup contents = tabHost.getContent();
- final int tabCount = parent.getTabCount();
- final int tabIndex = parent.getChildTabIndex(v);
-
- final int action = e.getAction();
- final boolean handleKeyEvent = (action != KeyEvent.ACTION_UP);
- boolean wasHandled = false;
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_LEFT:
- if (handleKeyEvent) {
- // Select the previous tab
- if (tabIndex > 0) {
- parent.getChildTabViewAt(tabIndex - 1).requestFocus();
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (handleKeyEvent) {
- // Select the next tab, or if the last tab has a focus right id, select that
- if (tabIndex < (tabCount - 1)) {
- parent.getChildTabViewAt(tabIndex + 1).requestFocus();
- } else {
- if (v.getNextFocusRightId() != View.NO_ID) {
- tabHost.findViewById(v.getNextFocusRightId()).requestFocus();
- }
- }
- }
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_UP:
- // Do nothing
- wasHandled = true;
- break;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- if (handleKeyEvent) {
- // Select the content view
- contents.requestFocus();
- }
- wasHandled = true;
- break;
- default: break;
- }
- return wasHandled;
- }
-
- /**
* Handles key events in the workspace hotseat (bottom of the screen).
*/
static boolean handleHotseatButtonKeyEvent(View v, int keyCode, KeyEvent e, int orientation) {
diff --git a/src/com/android/launcher3/FocusIndicatorView.java b/src/com/android/launcher3/FocusIndicatorView.java
index 12b7a40..7d4664a 100644
--- a/src/com/android/launcher3/FocusIndicatorView.java
+++ b/src/com/android/launcher3/FocusIndicatorView.java
@@ -16,6 +16,8 @@
package com.android.launcher3;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
@@ -28,6 +30,7 @@
// It can be any number >0. The view is resized using scaleX and scaleY.
static final int DEFAULT_LAYOUT_SIZE = 100;
private static final float MIN_VISIBLE_ALPHA = 0.2f;
+ private static final long ANIM_DURATION = 150;
private static final int[] sTempPos = new int[2];
private static final int[] sTempShift = new int[2];
@@ -35,6 +38,9 @@
private final int[] mIndicatorPos = new int[2];
private final int[] mTargetViewPos = new int[2];
+ private ObjectAnimator mCurrentAnimation;
+ private ViewAnimState mTargetState;
+
private View mLastFocusedView;
private boolean mInitiated;
@@ -82,34 +88,58 @@
int indicatorWidth = getWidth();
int indicatorHeight = getHeight();
- float scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
- float scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
+ endCurrentAnimation();
+ ViewAnimState nextState = new ViewAnimState();
+ nextState.scaleX = v.getScaleX() * v.getWidth() / indicatorWidth;
+ nextState.scaleY = v.getScaleY() * v.getHeight() / indicatorHeight;
getLocationRelativeToParentPagedView(v, mTargetViewPos);
- float x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - scaleX) * indicatorWidth / 2;
- float y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - scaleY) * indicatorHeight / 2;
+ nextState.x = mTargetViewPos[0] - mIndicatorPos[0] - (1 - nextState.scaleX) * indicatorWidth / 2;
+ nextState.y = mTargetViewPos[1] - mIndicatorPos[1] - (1 - nextState.scaleY) * indicatorHeight / 2;
if (getAlpha() > MIN_VISIBLE_ALPHA) {
- animate()
- .translationX(x)
- .translationY(y)
- .scaleX(scaleX)
- .scaleY(scaleY)
- .alpha(1);
+ mTargetState = nextState;
+ mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+ PropertyValuesHolder.ofFloat(View.ALPHA, 1),
+ PropertyValuesHolder.ofFloat(View.TRANSLATION_X, mTargetState.x),
+ PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, mTargetState.y),
+ PropertyValuesHolder.ofFloat(View.SCALE_X, mTargetState.scaleX),
+ PropertyValuesHolder.ofFloat(View.SCALE_Y, mTargetState.scaleY));
} else {
- setTranslationX(x);
- setTranslationY(y);
- setScaleX(scaleX);
- setScaleY(scaleY);
- animate().alpha(1);
+ applyState(nextState);
+ mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+ PropertyValuesHolder.ofFloat(View.ALPHA, 1));
}
mLastFocusedView = v;
} else {
if (mLastFocusedView == v) {
mLastFocusedView = null;
- animate().alpha(0);
+ endCurrentAnimation();
+ mCurrentAnimation = LauncherAnimUtils.ofPropertyValuesHolder(this,
+ PropertyValuesHolder.ofFloat(View.ALPHA, 0));
}
}
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.setDuration(ANIM_DURATION).start();
+ }
+ }
+
+ private void endCurrentAnimation() {
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.cancel();
+ mCurrentAnimation = null;
+ }
+ if (mTargetState != null) {
+ applyState(mTargetState);
+ mTargetState = null;
+ }
+ }
+
+ private void applyState(ViewAnimState state) {
+ setTranslationX(state.x);
+ setTranslationY(state.y);
+ setScaleX(state.scaleX);
+ setScaleY(state.scaleY);
}
@Override
@@ -143,4 +173,8 @@
shift[0] = shift[1] = 0;
}
}
+
+ private static final class ViewAnimState {
+ float x, y, scaleX, scaleY;
+ }
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 06f9f29..5a0875b 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -24,7 +24,6 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -117,8 +116,7 @@
}
public Drawable getFullResDefaultActivityIcon() {
- return getFullResIcon(Resources.getSystem(),
- android.R.mipmap.sym_def_app_icon);
+ return getFullResIcon(Resources.getSystem(), android.R.mipmap.sym_def_app_icon);
}
private Drawable getFullResIcon(Resources resources, int iconId) {
@@ -151,12 +149,7 @@
return mIconDpi;
}
- public Drawable getFullResIcon(ResolveInfo info) {
- return getFullResIcon(info.activityInfo);
- }
-
public Drawable getFullResIcon(ActivityInfo info) {
-
Resources resources;
try {
resources = mPackageManager.getResourcesForApplication(
@@ -190,16 +183,14 @@
/**
* Remove any records for the supplied ComponentName.
*/
- public void remove(ComponentName componentName, UserHandleCompat user) {
- synchronized (mCache) {
- mCache.remove(new CacheKey(componentName, user));
- }
+ public synchronized void remove(ComponentName componentName, UserHandleCompat user) {
+ mCache.remove(new CacheKey(componentName, user));
}
/**
* Remove any records for the supplied package name.
*/
- public void remove(String packageName, UserHandleCompat user) {
+ public synchronized void remove(String packageName, UserHandleCompat user) {
HashSet<CacheKey> forDeletion = new HashSet<CacheKey>();
for (CacheKey key: mCache.keySet()) {
if (key.componentName.getPackageName().equals(packageName)
@@ -215,24 +206,20 @@
/**
* Empty out the cache.
*/
- public void flush() {
- synchronized (mCache) {
- mCache.clear();
- }
+ public synchronized void flush() {
+ mCache.clear();
}
/**
* Empty out the cache that aren't of the correct grid size
*/
- public void flushInvalidIcons(DeviceProfile grid) {
- synchronized (mCache) {
- Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
- while (it.hasNext()) {
- final CacheEntry e = it.next().getValue();
- if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
- || e.icon.getHeight() < grid.iconSizePx)) {
- it.remove();
- }
+ public synchronized void flushInvalidIcons(DeviceProfile grid) {
+ Iterator<Entry<CacheKey, CacheEntry>> it = mCache.entrySet().iterator();
+ while (it.hasNext()) {
+ final CacheEntry e = it.next().getValue();
+ if ((e.icon != null) && (e.icon.getWidth() < grid.iconSizePx
+ || e.icon.getHeight() < grid.iconSizePx)) {
+ it.remove();
}
}
}
@@ -240,90 +227,78 @@
/**
* Fill in "application" with the icon and label for "info."
*/
- public void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
+ public synchronized void getTitleAndIcon(AppInfo application, LauncherActivityInfoCompat info,
HashMap<Object, CharSequence> labelCache) {
- synchronized (mCache) {
- CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
- info.getUser(), false);
+ CacheEntry entry = cacheLocked(application.componentName, info, labelCache,
+ info.getUser(), false);
- application.title = entry.title;
- application.iconBitmap = entry.icon;
- application.contentDescription = entry.contentDescription;
- }
+ application.title = entry.title;
+ application.iconBitmap = entry.icon;
+ application.contentDescription = entry.contentDescription;
}
- public Bitmap getIcon(Intent intent, UserHandleCompat user) {
- return getIcon(intent, null, user, true);
- }
-
- private Bitmap getIcon(Intent intent, String title, UserHandleCompat user, boolean usePkgIcon) {
- synchronized (mCache) {
- ComponentName component = intent.getComponent();
- // null info means not installed, but if we have a component from the intent then
- // we should still look in the cache for restored app icons.
- if (component == null) {
- return getDefaultIcon(user);
- }
-
- LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
- CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
- if (title != null) {
- entry.title = title;
- entry.contentDescription = mUserManager.getBadgedLabelForUser(title, user);
- }
- return entry.icon;
+ public synchronized Bitmap getIcon(Intent intent, UserHandleCompat user) {
+ ComponentName component = intent.getComponent();
+ // null info means not installed, but if we have a component from the intent then
+ // we should still look in the cache for restored app icons.
+ if (component == null) {
+ return getDefaultIcon(user);
}
+
+ LauncherActivityInfoCompat launcherActInfo = mLauncherApps.resolveActivity(intent, user);
+ CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, true);
+ return entry.icon;
}
/**
* Fill in "shortcutInfo" with the icon and label for "info."
*/
- public void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent, UserHandleCompat user,
- boolean usePkgIcon) {
- synchronized (mCache) {
- ComponentName component = intent.getComponent();
- // null info means not installed, but if we have a component from the intent then
- // we should still look in the cache for restored app icons.
- if (component == null) {
- shortcutInfo.setIcon(getDefaultIcon(user));
- shortcutInfo.title = "";
- shortcutInfo.usingFallbackIcon = true;
- } else {
- LauncherActivityInfoCompat launcherActInfo =
- mLauncherApps.resolveActivity(intent, user);
- CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
+ public synchronized void getTitleAndIcon(ShortcutInfo shortcutInfo, Intent intent,
+ UserHandleCompat user, boolean usePkgIcon) {
+ ComponentName component = intent.getComponent();
+ // null info means not installed, but if we have a component from the intent then
+ // we should still look in the cache for restored app icons.
+ if (component == null) {
+ shortcutInfo.setIcon(getDefaultIcon(user));
+ shortcutInfo.title = "";
+ shortcutInfo.usingFallbackIcon = true;
+ } else {
+ LauncherActivityInfoCompat launcherActInfo =
+ mLauncherApps.resolveActivity(intent, user);
+ CacheEntry entry = cacheLocked(component, launcherActInfo, null, user, usePkgIcon);
- shortcutInfo.setIcon(entry.icon);
- shortcutInfo.title = entry.title;
- shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
- }
+ shortcutInfo.setIcon(entry.icon);
+ shortcutInfo.title = entry.title;
+ shortcutInfo.usingFallbackIcon = isDefaultIcon(entry.icon, user);
}
}
- public Bitmap getDefaultIcon(UserHandleCompat user) {
+ public synchronized Bitmap getDefaultIcon(UserHandleCompat user) {
if (!mDefaultIcons.containsKey(user)) {
mDefaultIcons.put(user, makeDefaultIcon(user));
}
return mDefaultIcons.get(user);
}
- public Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
+ public synchronized Bitmap getIcon(ComponentName component, LauncherActivityInfoCompat info,
HashMap<Object, CharSequence> labelCache) {
- synchronized (mCache) {
- if (info == null || component == null) {
- return null;
- }
-
- CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
- return entry.icon;
+ if (info == null || component == null) {
+ return null;
}
+
+ CacheEntry entry = cacheLocked(component, info, labelCache, info.getUser(), false);
+ return entry.icon;
}
public boolean isDefaultIcon(Bitmap icon, UserHandleCompat user) {
return mDefaultIcons.get(user) == icon;
}
+ /**
+ * Retrieves the entry from the cache. If the entry is not present, it creates a new entry.
+ * This method is not thread safe, it must be called from a synchronized method.
+ */
private CacheEntry cacheLocked(ComponentName componentName, LauncherActivityInfoCompat info,
HashMap<Object, CharSequence> labelCache, UserHandleCompat user, boolean usePackageIcon) {
CacheKey cacheKey = new CacheKey(componentName, user);
@@ -380,7 +355,7 @@
* Adds a default package entry in the cache. This entry is not persisted and will be removed
* when the cache is flushed.
*/
- public void cachePackageInstallInfo(String packageName, UserHandleCompat user,
+ public synchronized void cachePackageInstallInfo(String packageName, UserHandleCompat user,
Bitmap icon, CharSequence title) {
remove(packageName, user);
@@ -395,9 +370,10 @@
/**
* Gets an entry for the package, which can be used as a fallback entry for various components.
+ * This method is not thread safe, it must be called from a synchronized method.
*/
private CacheEntry getEntryForPackage(String packageName, UserHandleCompat user) {
- ComponentName cn = getPackageComponent(packageName);
+ ComponentName cn = new ComponentName(packageName, EMPTY_CLASS_NAME);;
CacheKey cacheKey = new CacheKey(cn, user);
CacheEntry entry = mCache.get(cacheKey);
if (entry == null) {
@@ -420,15 +396,13 @@
return entry;
}
- public HashMap<ComponentName,Bitmap> getAllIcons() {
- synchronized (mCache) {
- HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
- for (CacheKey ck : mCache.keySet()) {
- final CacheEntry e = mCache.get(ck);
- set.put(ck.componentName, e.icon);
- }
- return set;
+ public synchronized HashMap<ComponentName,Bitmap> getAllIcons() {
+ HashMap<ComponentName,Bitmap> set = new HashMap<ComponentName,Bitmap>();
+ for (CacheKey ck : mCache.keySet()) {
+ final CacheEntry e = mCache.get(ck);
+ set.put(ck.componentName, e.icon);
}
+ return set;
}
/**
@@ -534,23 +508,15 @@
* Remove a pre-loaded icon from the persistent icon cache.
*
* @param componentName the component that should own the icon
- * @returns true on success
*/
- public boolean deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
+ public void deletePreloadedIcon(ComponentName componentName, UserHandleCompat user) {
// We don't keep icons for other profiles in persistent cache.
- if (!user.equals(UserHandleCompat.myUserHandle())) {
- return false;
+ if (!user.equals(UserHandleCompat.myUserHandle()) || componentName == null) {
+ return;
}
- if (componentName == null) {
- return false;
- }
- if (mCache.remove(componentName) != null) {
- if (DEBUG) Log.d(TAG, "removed pre-loaded icon from the in-memory cache");
- }
+ remove(componentName, user);
boolean success = mContext.deleteFile(getResourceFilename(componentName));
if (DEBUG && success) Log.d(TAG, "removed pre-loaded icon from persistent cache");
-
- return success;
}
private static String getResourceFilename(ComponentName component) {
@@ -558,8 +524,4 @@
String filename = resourceName.replace(File.separatorChar, '_');
return RESOURCE_FILE_PREFIX + filename;
}
-
- static ComponentName getPackageComponent(String packageName) {
- return new ComponentName(packageName, EMPTY_CLASS_NAME);
- }
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index d5cb55b..309837f 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -86,6 +86,7 @@
import android.view.View.OnLongClickListener;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
+import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
@@ -125,6 +126,7 @@
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -227,6 +229,10 @@
private boolean mIsSafeModeEnabled;
+ LauncherOverlayCallbacks mLauncherOverlayCallbacks = new LauncherOverlayCallbacksImpl();
+ LauncherOverlay mLauncherOverlay;
+ ViewGroup mLauncherOverlayView;
+
static final int APPWIDGET_HOST_ID = 1024;
public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
@@ -506,6 +512,13 @@
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
+ if (mLauncherCallbacks.hasLauncherOverlay()) {
+ ViewStub stub = (ViewStub) findViewById(R.id.launcher_overlay_stub);
+ mLauncherOverlayView = (ViewGroup) stub.inflate();
+ mLauncherOverlay = mLauncherCallbacks.setLauncherOverlayView(mLauncherOverlayView,
+ mLauncherOverlayCallbacks);
+ mWorkspace.setLauncherOverlay(mLauncherOverlay);
+ }
}
}
@@ -1144,6 +1157,84 @@
boolean isScrollingAllowed();
}
+ public interface LauncherOverlay {
+
+ /**
+ * Touch interaction leading to overscroll has begun
+ */
+ public void onScrollInteractionBegin();
+
+ /**
+ * Touch interaction related to overscroll has ended
+ */
+ public void onScrollInteractionEnd();
+
+ /**
+ * Scroll progress, between 0 and 100, when the user scrolls beyond the leftmost
+ * screen (or in the case of RTL, the rightmost screen).
+ */
+ public void onScrollChange(int progress, boolean rtl);
+
+ /**
+ * Screen has stopped scrolling
+ */
+ public void onScrollSettled();
+
+ /**
+ * This method can be called by the Launcher in order to force the LauncherOverlay
+ * to exit fully immersive mode.
+ */
+ public void forceExitFullImmersion();
+ }
+
+ public interface LauncherOverlayCallbacks {
+ /**
+ * This method indicates whether a call to {@link #enterFullImmersion()} will succeed,
+ * however it doesn't modify any state within the launcher.
+ */
+ public boolean canEnterFullImmersion();
+
+ /**
+ * Should be called to tell Launcher that the LauncherOverlay will take over interaction,
+ * eg. by occupying the full screen and handling all touch events.
+ *
+ * @return true if Launcher allows the LauncherOverlay to become fully immersive. In this
+ * case, Launcher will modify any necessary state and assumes the overlay is
+ * handling all interaction. If false, the LauncherOverlay should cancel any
+ *
+ */
+ public boolean enterFullImmersion();
+
+ /**
+ * Must be called when exiting fully immersive mode. Indicates to Launcher that it has
+ * full control over UI and state.
+ */
+ public void exitFullImmersion();
+ }
+
+ class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks {
+
+ @Override
+ public boolean canEnterFullImmersion() {
+ return mState == State.WORKSPACE;
+ }
+
+ @Override
+ public boolean enterFullImmersion() {
+ if (mState == State.WORKSPACE) {
+ // When fully immersed, disregard any touches which fall through.
+ mDragLayer.setBlockTouch(true);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void exitFullImmersion() {
+ mDragLayer.setBlockTouch(false);
+ }
+ }
+
protected boolean hasSettings() {
if (mLauncherCallbacks != null) {
return mLauncherCallbacks.hasSettings();
@@ -1369,9 +1460,6 @@
settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
} else {
settingsButton.setVisibility(View.GONE);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) widgetButton.getLayoutParams();
- lp.gravity = Gravity.END | Gravity.TOP;
- widgetButton.requestLayout();
}
mOverviewPanel.setAlpha(0f);
@@ -2066,7 +2154,6 @@
mWorkspace = null;
mDragController = null;
- PackageInstallerCompat.getInstance(this).onStop();
LauncherAnimUtils.onDestroyActivity();
if (mLauncherCallbacks != null) {
@@ -2538,6 +2625,11 @@
* Event handler for the app widget view which has not fully restored.
*/
public void onClickPendingWidget(final PendingAppWidgetHostView v) {
+ if (mIsSafeModeEnabled) {
+ Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+ return;
+ }
+
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
if (v.isReadyForClickSetup()) {
int widgetId = info.appWidgetId;
@@ -2790,10 +2882,13 @@
*/
protected void onClickAddWidgetButton(View view) {
if (LOGD) Log.d(TAG, "onClickAddWidgetButton");
- showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
-
- if (mLauncherCallbacks != null) {
- mLauncherCallbacks.onClickAddWidgetButton(view);
+ if (mIsSafeModeEnabled) {
+ Toast.makeText(this, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+ } else {
+ showAllApps(true, AppsCustomizePagedView.ContentType.Widgets, true);
+ if (mLauncherCallbacks != null) {
+ mLauncherCallbacks.onClickAddWidgetButton(view);
+ }
}
}
@@ -4079,11 +4174,8 @@
}
public View getQsbBar() {
- if (mLauncherCallbacks != null) {
- View qsb = mLauncherCallbacks.getQsbBar();
- if (qsb != null) {
- return qsb;
- }
+ if (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch()) {
+ return mLauncherCallbacks.getQsbBar();
}
if (mQsb == null) {
@@ -4591,8 +4683,9 @@
final Workspace workspace = mWorkspace;
AppWidgetProviderInfo appWidgetInfo;
- if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) &&
- ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
+ if (!mIsSafeModeEnabled
+ && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0)
+ && ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) {
appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName);
if (appWidgetInfo == null) {
@@ -4642,7 +4735,7 @@
LauncherModel.updateItemInDatabase(this, item);
}
- if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
+ if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
final int appWidgetId = item.appWidgetId;
appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
if (DEBUG_WIDGETS) {
@@ -4652,7 +4745,8 @@
item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
} else {
appWidgetInfo = null;
- PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item);
+ PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item,
+ mIsSafeModeEnabled);
view.updateIcon(mIconCache);
item.hostView = view;
item.hostView.updateAppWidget(null);
@@ -4851,33 +4945,54 @@
return;
}
- if (mWorkspace != null) {
- mWorkspace.updateShortcutsAndWidgets(apps);
- }
-
if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
mAppsCustomizeContent.updateApps(apps);
}
}
+ @Override
+ public void bindWidgetsRestored(final ArrayList<LauncherAppWidgetInfo> widgets) {
+ Runnable r = new Runnable() {
+ public void run() {
+ bindWidgetsRestored(widgets);
+ }
+ };
+ if (waitUntilResume(r)) {
+ return;
+ }
+ mWorkspace.widgetsRestored(widgets);
+ }
+
/**
* Some shortcuts were updated in the background.
*
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void bindShortcutsUpdated(final ArrayList<ShortcutInfo> shortcuts) {
+ @Override
+ public void bindShortcutsChanged(final ArrayList<ShortcutInfo> updated,
+ final ArrayList<ShortcutInfo> removed, final UserHandleCompat user) {
Runnable r = new Runnable() {
public void run() {
- bindShortcutsUpdated(shortcuts);
+ bindShortcutsChanged(updated, removed, user);
}
};
if (waitUntilResume(r)) {
return;
}
- if (mWorkspace != null) {
- mWorkspace.updateShortcuts(shortcuts);
+ if (!updated.isEmpty()) {
+ mWorkspace.updateShortcuts(updated);
+ }
+
+ if (!removed.isEmpty()) {
+ HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
+ for (ShortcutInfo si : removed) {
+ removedComponents.add(si.getTargetComponent());
+ }
+ mWorkspace.removeItemsByComponentName(removedComponents, user);
+ // Notify the drag controller
+ mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents);
}
}
@@ -4928,19 +5043,23 @@
}
if (reason == 0) {
+ HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
+ for (AppInfo info : appInfos) {
+ removedComponents.add(info.componentName);
+ }
if (!packageNames.isEmpty()) {
mWorkspace.removeItemsByPackageName(packageNames, user);
}
- if (!appInfos.isEmpty()) {
- mWorkspace.removeItemsByApplicationInfo(appInfos, user);
+ if (!removedComponents.isEmpty()) {
+ mWorkspace.removeItemsByComponentName(removedComponents, user);
}
+ // Notify the drag controller
+ mDragController.onAppsRemoved(packageNames, removedComponents);
+
} else {
mWorkspace.disableShortcutsByPackageName(packageNames, user, reason);
}
- // Notify the drag controller
- mDragController.onAppsRemoved(packageNames, appInfos);
-
// Update AllApps
if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 893d49f..03ab94b 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -29,6 +29,7 @@
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import java.lang.ref.WeakReference;
@@ -134,6 +135,7 @@
sContext.unregisterReceiver(mModel);
final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
launcherApps.removeOnAppsChangedCallback(mModel);
+ PackageInstallerCompat.getInstance(sContext).onStop();
ContentResolver resolver = sContext.getContentResolver();
resolver.unregisterContentObserver(mFavoritesObserver);
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index aef2adc..e0cfa27 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -6,6 +6,7 @@
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
+import android.view.ViewGroup;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -86,4 +87,22 @@
public boolean overrideWallpaperDimensions();
public boolean isLauncherPreinstalled();
+ /**
+ * Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup,
+ * com.android.launcher3.Launcher.LauncherOverlayCallbacks)}.
+ *
+ * @return true if this launcher extension will provide an overlay
+ */
+ public boolean hasLauncherOverlay();
+
+ /**
+ * Handshake to establish an overlay relationship
+ *
+ * @param overlayView 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,
+ Launcher.LauncherOverlayCallbacks callbacks);
+
}
diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java
new file mode 100644
index 0000000..10bbd35
--- /dev/null
+++ b/src/com/android/launcher3/LauncherExtension.java
@@ -0,0 +1,354 @@
+package com.android.launcher3;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * This class represents a very trivial LauncherExtension. It primarily serves as a simple
+ * class to exercise the LauncherOverlay interface.
+ */
+public class LauncherExtension extends Launcher {
+
+ //------ Activity methods -------//
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ setLauncherCallbacks(new LauncherExtensionCallbacks());
+ super.onCreate(savedInstanceState);
+ }
+
+ public class LauncherExtensionCallbacks implements LauncherCallbacks {
+
+ LauncherExtensionOverlay mLauncherOverlay = new LauncherExtensionOverlay();
+
+ @Override
+ public void preOnCreate() {
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ }
+
+ @Override
+ public void preOnResume() {
+ }
+
+ @Override
+ public void onResume() {
+ }
+
+ @Override
+ public void onStart() {
+ }
+
+ @Override
+ public void onStop() {
+ }
+
+ @Override
+ public void onPause() {
+ }
+
+ @Override
+ public void onDestroy() {
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ }
+
+ @Override
+ public void onPostCreate(Bundle savedInstanceState) {
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ }
+
+ @Override
+ public void onWindowFocusChanged(boolean hasFocus) {
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ return false;
+ }
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter w, String[] args) {
+ }
+
+ @Override
+ public void onHomeIntent() {
+ }
+
+ @Override
+ public boolean handleBackPressed() {
+ if (mLauncherOverlay.isOverlayPanelShowing()) {
+ mLauncherOverlay.hideOverlayPanel();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onLauncherProviderChange() {
+ }
+
+ @Override
+ public void finishBindingItems(boolean upgradePath) {
+ }
+
+ @Override
+ public void onClickAllAppsButton(View v) {
+ }
+
+ @Override
+ public void bindAllApplications(ArrayList<AppInfo> apps) {
+ }
+
+ @Override
+ public void onClickFolderIcon(View v) {
+ }
+
+ @Override
+ public void onClickAppShortcut(View v) {
+ }
+
+ @Override
+ public void onClickPagedViewIcon(View v) {
+ }
+
+ @Override
+ public void onClickWallpaperPicker(View v) {
+ }
+
+ @Override
+ public void onClickSettingsButton(View v) {
+ }
+
+ @Override
+ public void onClickAddWidgetButton(View v) {
+ }
+
+ @Override
+ public void onPageSwitch(View newPage, int newPageIndex) {
+ }
+
+ @Override
+ public void onWorkspaceLockedChanged() {
+ }
+
+ @Override
+ public void onDragStarted(View view) {
+ }
+
+ @Override
+ public void onInteractionBegin() {
+ }
+
+ @Override
+ public void onInteractionEnd() {
+ }
+
+ @Override
+ public boolean forceDisableVoiceButtonProxy() {
+ return false;
+ }
+
+ @Override
+ public boolean providesSearch() {
+ return true;
+ }
+
+ @Override
+ public boolean startSearch(String initialQuery, boolean selectInitialQuery,
+ Bundle appSearchData, Rect sourceBounds) {
+ return false;
+ }
+
+ @Override
+ public void startVoice() {
+ }
+
+ @Override
+ public boolean hasCustomContentToLeft() {
+ return false;
+ }
+
+ @Override
+ public void populateCustomContentContainer() {
+ }
+
+ @Override
+ public View getQsbBar() {
+ return mLauncherOverlay.getSearchBox();
+ }
+
+ @Override
+ public Intent getFirstRunActivity() {
+ return null;
+ }
+
+ @Override
+ public boolean hasFirstRunActivity() {
+ return false;
+ }
+
+ @Override
+ public boolean hasDismissableIntroScreen() {
+ return false;
+ }
+
+ @Override
+ public View getIntroScreen() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldMoveToDefaultScreenOnHomeIntent() {
+ return true;
+ }
+
+ @Override
+ public boolean hasSettings() {
+ return false;
+ }
+
+ @Override
+ public ComponentName getWallpaperPickerComponent() {
+ return null;
+ }
+
+ @Override
+ public boolean overrideWallpaperDimensions() {
+ return false;
+ }
+
+ @Override
+ public boolean isLauncherPreinstalled() {
+ return false;
+ }
+
+ @Override
+ public boolean hasLauncherOverlay() {
+ return true;
+ }
+
+ @Override
+ public LauncherOverlay setLauncherOverlayView(ViewGroup overlayView,
+ LauncherOverlayCallbacks callbacks) {
+
+ mLauncherOverlay.setOverlayCallbacks(callbacks);
+ mLauncherOverlay.setOverlayView(overlayView);
+
+ return mLauncherOverlay;
+ }
+
+ class LauncherExtensionOverlay implements LauncherOverlay {
+ LauncherOverlayCallbacks mLauncherOverlayCallbacks;
+ ViewGroup mOverlayView;
+ View mSearchBox;
+ View mSearchOverlay;
+ boolean mShowOverlayFeedback;
+ int mProgress;
+ boolean mOverlayPanelShowing;
+
+ @Override
+ public void onScrollInteractionBegin() {
+ if (mLauncherOverlayCallbacks.canEnterFullImmersion()) {
+ mShowOverlayFeedback = true;
+ updatePanelOffset(0);
+ mSearchOverlay.setVisibility(View.VISIBLE);
+ mSearchOverlay.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+ }
+
+ @Override
+ public void onScrollChange(int progress, boolean rtl) {
+ mProgress = progress;
+ if (mShowOverlayFeedback) {
+ updatePanelOffset(progress);
+ }
+ }
+
+ private void updatePanelOffset(int progress) {
+ int panelWidth = mSearchOverlay.getMeasuredWidth();
+ int offset = (int) ((progress / 100f) * panelWidth);
+ mSearchOverlay.setTranslationX(- panelWidth + offset);
+ }
+
+ @Override
+ public void onScrollInteractionEnd() {
+ if (mProgress > 25 && mLauncherOverlayCallbacks.enterFullImmersion()) {
+ ObjectAnimator oa = LauncherAnimUtils.ofFloat(mSearchOverlay, "translationX", 0);
+ oa.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ oa.start();
+ mOverlayPanelShowing = true;
+ mShowOverlayFeedback = false;
+ }
+ }
+
+ @Override
+ public void onScrollSettled() {
+ if (mShowOverlayFeedback) {
+ mSearchOverlay.setVisibility(View.INVISIBLE);
+ mSearchOverlay.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ mShowOverlayFeedback = false;
+ mProgress = 0;
+ }
+
+ public void hideOverlayPanel() {
+ mLauncherOverlayCallbacks.exitFullImmersion();
+ mSearchOverlay.setVisibility(View.INVISIBLE);
+ mOverlayPanelShowing = false;
+ }
+
+ public boolean isOverlayPanelShowing() {
+ return mOverlayPanelShowing;
+ }
+
+ @Override
+ public void forceExitFullImmersion() {
+ hideOverlayPanel();
+ }
+
+ public void setOverlayView(ViewGroup overlayView) {
+ mOverlayView = (ViewGroup) getLayoutInflater().inflate(
+ R.layout.launcher_overlay_example, overlayView);
+ mSearchOverlay = mOverlayView.findViewById(R.id.search_overlay);
+ mSearchBox = mOverlayView.findViewById(R.id.search_box);
+ }
+
+ public View getSearchBox() {
+ return mSearchBox;
+ }
+
+ public void setOverlayCallbacks(LauncherOverlayCallbacks callbacks) {
+ mLauncherOverlayCallbacks = callbacks;
+ }
+ };
+ }
+}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 3055dd0..b04fc3f 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -198,7 +198,9 @@
ArrayList<ItemInfo> addAnimated,
ArrayList<AppInfo> addedApps);
public void bindAppsUpdated(ArrayList<AppInfo> apps);
- public void bindShortcutsUpdated(ArrayList<ShortcutInfo> shortcuts);
+ public void bindShortcutsChanged(ArrayList<ShortcutInfo> updated,
+ ArrayList<ShortcutInfo> removed, UserHandleCompat user);
+ public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
public void updatePackageState(ArrayList<PackageInstallInfo> installInfo);
public void updatePackageBadge(String packageName);
public void bindComponentsRemoved(ArrayList<String> packageNames,
@@ -373,15 +375,6 @@
return;
}
- final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
- Iterator<AppInfo> iter = allAppsApps.iterator();
- while (iter.hasNext()) {
- ItemInfo a = iter.next();
- if (LauncherModel.appWasPromise(ctx, a.getIntent(), a.user)) {
- restoredAppsFinal.add((AppInfo) a);
- }
- }
-
// Process the newly added applications and add them to the database first
Runnable r = new Runnable() {
public void run() {
@@ -389,16 +382,6 @@
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks == cb && cb != null) {
- if (!restoredAppsFinal.isEmpty()) {
- for (AppInfo info : restoredAppsFinal) {
- final Intent intent = info.getIntent();
- if (intent != null) {
- mIconCache.deletePreloadedIcon(intent.getComponent(),
- info.user);
- }
- }
- callbacks.bindAppsUpdated(restoredAppsFinal);
- }
callbacks.bindAppsAdded(null, null, null, allAppsApps);
}
}
@@ -423,7 +406,6 @@
public void run() {
final ArrayList<ItemInfo> addedShortcutsFinal = new ArrayList<ItemInfo>();
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<Long>();
- final ArrayList<AppInfo> restoredAppsFinal = new ArrayList<AppInfo>();
// Get the list of workspace screens. We need to append to this list and
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
@@ -443,12 +425,7 @@
final Intent launchIntent = a.getIntent();
// Short-circuit this logic if the icon exists somewhere on the workspace
- if (LauncherModel.shortcutExists(context, name, launchIntent)) {
- // Only InstallShortcutReceiver sends us shortcutInfos, ignore them
- if (a instanceof AppInfo &&
- LauncherModel.appWasPromise(context, launchIntent, a.user)) {
- restoredAppsFinal.add((AppInfo) a);
- }
+ if (shortcutExists(context, name, launchIntent)) {
continue;
}
@@ -524,9 +501,6 @@
}
callbacks.bindAppsAdded(addedWorkspaceScreensFinal,
addNotAnimated, addAnimated, null);
- if (!restoredAppsFinal.isEmpty()) {
- callbacks.bindAppsUpdated(restoredAppsFinal);
- }
}
}
});
@@ -902,17 +876,6 @@
}
/**
- * Returns true if the promise shortcuts with the same package name exists on the workspace.
- */
- static boolean appWasPromise(Context context, Intent intent, UserHandleCompat user) {
- final ComponentName component = intent.getComponent();
- if (component == null) {
- return false;
- }
- return !getItemsByPackageName(component.getPackageName(), user).isEmpty();
- }
-
- /**
* Returns an ItemInfo array containing all the items in the LauncherModel.
* The ItemInfo.id is not set through this function.
*/
@@ -1111,7 +1074,7 @@
* @param context
* @param item
*/
- static void deleteItemsFromDatabase(Context context, final ArrayList<ItemInfo> items) {
+ static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
final ContentResolver cr = context.getContentResolver();
Runnable r = new Runnable() {
@@ -2268,7 +2231,7 @@
// App restore has started. Update the flag
appWidgetInfo.restoreStatus |=
LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
- } else if (REMOVE_UNRESTORED_ICONS) {
+ } else if (REMOVE_UNRESTORED_ICONS && !isSafeMode) {
Launcher.addDumpLog(TAG,
"Unrestored widget removed: " + component, true);
itemsToRemove.add(id);
@@ -3034,6 +2997,9 @@
return;
}
+ final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
+ new HashMap<ComponentName, AppInfo>();
+
if (added != null) {
// Ensure that we add all the workspace applications to the db
if (LauncherAppState.isDisableAllApps()) {
@@ -3042,23 +3008,15 @@
} else {
addAppsToAllApps(context, added);
}
+ for (AppInfo ai : added) {
+ addedOrUpdatedApps.put(ai.componentName, ai);
+ }
}
if (modified != null) {
final ArrayList<AppInfo> modifiedFinal = modified;
-
- // Update the launcher db to reflect the changes
- for (AppInfo a : modifiedFinal) {
- ArrayList<ItemInfo> infos =
- getItemInfoForComponentName(a.componentName, mUser);
- for (ItemInfo i : infos) {
- if (i instanceof ShortcutInfo && isShortcutAppTarget((ShortcutInfo) i)) {
- ShortcutInfo info = (ShortcutInfo) i;
- info.title = a.title.toString();
- info.contentDescription = a.contentDescription;
- updateItemInDatabase(context, info);
- }
- }
+ for (AppInfo ai : modified) {
+ addedOrUpdatedApps.put(ai.componentName, ai);
}
mHandler.post(new Runnable() {
@@ -3071,37 +3029,128 @@
});
}
- // Update shortcuts which use an iconResource
+ // Update shortcut infos
if (mOp == OP_ADD || mOp == OP_UPDATE) {
- final ArrayList<ShortcutInfo> iconsChanged = new ArrayList<ShortcutInfo>();
+ final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
+ final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
+ final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
+
HashSet<String> packageSet = new HashSet<String>(Arrays.asList(packages));
- // We need to iterate over the items here, so that we can avoid new Bitmap
- // creation on the UI thread.
synchronized (sBgLock) {
- for (ItemInfo info : sBgWorkspaceItems) {
+ for (ItemInfo info : sBgItemsIdMap.values()) {
if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
ShortcutInfo si = (ShortcutInfo) info;
+ boolean infoUpdated = false;
+ boolean shortcutUpdated = false;
+
+ // Update shortcuts which use iconResource.
if ((si.iconResource != null)
- && packageSet.contains(si.getTargetComponent().getPackageName())){
+ && packageSet.contains(si.iconResource.packageName)) {
Bitmap icon = Utilities.createIconBitmap(si.iconResource.packageName,
si.iconResource.resourceName, mIconCache, context);
if (icon != null) {
si.setIcon(icon);
si.usingFallbackIcon = false;
- iconsChanged.add(si);
- updateItemInDatabase(context, si);
+ infoUpdated = true;
}
}
+
+ ComponentName cn = si.getTargetComponent();
+ if (cn != null && packageSet.contains(cn.getPackageName())) {
+ AppInfo appInfo = addedOrUpdatedApps.get(cn);
+
+ if (si.isPromise()) {
+ mIconCache.deletePreloadedIcon(cn, mUser);
+ if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
+ // Auto install icon
+ PackageManager pm = context.getPackageManager();
+ ResolveInfo matched = pm.resolveActivity(
+ new Intent(Intent.ACTION_MAIN)
+ .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
+ PackageManager.MATCH_DEFAULT_ONLY);
+ if (matched == null) {
+ // Try to find the best match activity.
+ Intent intent = pm.getLaunchIntentForPackage(
+ cn.getPackageName());
+ if (intent != null) {
+ cn = intent.getComponent();
+ appInfo = addedOrUpdatedApps.get(cn);
+ }
+
+ if ((intent == null) || (appInfo == null)) {
+ removedShortcuts.add(si);
+ continue;
+ }
+ si.promisedIntent = intent;
+ }
+ }
+
+ // Restore the shortcut.
+ si.intent = si.promisedIntent;
+ si.promisedIntent = null;
+ si.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
+ & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
+ & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
+
+ infoUpdated = true;
+ si.updateIcon(mIconCache);
+ }
+
+ if (appInfo != null && Intent.ACTION_MAIN.equals(si.intent.getAction())
+ && si.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ si.updateIcon(mIconCache);
+ si.title = appInfo.title.toString();
+ si.contentDescription = appInfo.contentDescription;
+ infoUpdated = true;
+ }
+
+ if ((si.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
+ // Since package was just updated, the target must be available now.
+ si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
+ shortcutUpdated = true;
+ }
+ }
+
+ if (infoUpdated || shortcutUpdated) {
+ updatedShortcuts.add(si);
+ }
+ if (infoUpdated) {
+ updateItemInDatabase(context, si);
+ }
+ } else if (info instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
+ if (mUser.equals(widgetInfo.user)
+ && widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
+ && packageSet.contains(widgetInfo.providerName.getPackageName())) {
+ widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
+ widgets.add(widgetInfo);
+ updateItemInDatabase(context, widgetInfo);
+ }
}
}
}
- if (!iconsChanged.isEmpty()) {
+ if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
+ mHandler.post(new Runnable() {
+
+ public void run() {
+ Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == cb && cb != null) {
+ callbacks.bindShortcutsChanged(
+ updatedShortcuts, removedShortcuts, mUser);
+ }
+ }
+ });
+ if (!removedShortcuts.isEmpty()) {
+ deleteItemsFromDatabase(context, removedShortcuts);
+ }
+ }
+ if (!widgets.isEmpty()) {
mHandler.post(new Runnable() {
public void run() {
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
if (callbacks == cb && cb != null) {
- callbacks.bindShortcutsUpdated(iconsChanged);
+ callbacks.bindWidgetsRestored(widgets);
}
}
});
@@ -3401,20 +3450,6 @@
}
/**
- * @return true if the ShortcutInfo points to an app shortcut target, i.e. it has been added by
- * dragging from AllApps list.
- */
- public static boolean isShortcutAppTarget(ShortcutInfo info) {
- // We need to check for ACTION_MAIN otherwise getComponent() might
- // return null for some shortcuts (for instance, for shortcuts to
- // web pages.)
- Intent intent = info.promisedIntent != null ? info.promisedIntent : info.intent;
- ComponentName name = intent.getComponent();
- return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
- Intent.ACTION_MAIN.equals(intent.getAction()) && name != null;
- }
-
- /**
* Make an ShortcutInfo object for a shortcut that isn't an application.
*/
private ShortcutInfo getShortcutInfo(Cursor c, Context context,
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 7a0a8fa..9150dc0 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -31,12 +31,7 @@
import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
@@ -46,7 +41,6 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -58,11 +52,7 @@
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.ProviderConfig;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import java.io.File;
-import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
@@ -89,9 +79,6 @@
static final String EMPTY_DATABASE_CREATED =
"EMPTY_DATABASE_CREATED";
- private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
- "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";
-
private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
private LauncherProviderChangeListener mListener;
@@ -160,12 +147,6 @@
return db.insert(table, nullColumnHack, values);
}
- private static void deleteId(SQLiteDatabase db, long id) {
- Uri uri = LauncherSettings.Favorites.getContentUri(id, false);
- SqlArguments args = new SqlArguments(uri, null, null);
- db.delete(args.table, args.where, args.args);
- }
-
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
SqlArguments args = new SqlArguments(uri);
@@ -325,7 +306,7 @@
if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
Log.d(TAG, "loading default workspace");
- WorkspaceLoader loader = AutoInstallsLayout.get(getContext(),
+ AutoInstallsLayout loader = AutoInstallsLayout.get(getContext(),
mOpenHelper.mAppWidgetHost, mOpenHelper);
if (loader == null) {
@@ -335,14 +316,15 @@
int workspaceResId = partnerRes.getIdentifier(Partner.RES_DEFAULT_LAYOUT,
"xml", partner.getPackageName());
if (workspaceResId != 0) {
- loader = new SimpleWorkspaceLoader(mOpenHelper, partnerRes, workspaceResId);
+ loader = new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost,
+ mOpenHelper, partnerRes, workspaceResId);
}
}
}
if (loader == null) {
- loader = new SimpleWorkspaceLoader(mOpenHelper, getContext().getResources(),
- getDefaultWorkspaceResourceId());
+ loader = new DefaultLayoutParser(getContext(), mOpenHelper.mAppWidgetHost,
+ mOpenHelper, getContext().getResources(), getDefaultWorkspaceResourceId());
}
// Populate favorites table with initial favorites
@@ -360,11 +342,7 @@
private static int getDefaultWorkspaceResourceId() {
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- if (LauncherAppState.isDisableAllApps()) {
- return grid.defaultNoAllAppsLayoutId;
- } else {
- return grid.defaultLayoutId;
- }
+ return grid.defaultLayoutId;
}
private static interface ContentValuesCallback {
@@ -390,38 +368,7 @@
}
private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback {
- private static final String TAG_RESOLVE = "resolve";
- private static final String TAG_FAVORITES = "favorites";
- private static final String TAG_FAVORITE = "favorite";
- private static final String TAG_APPWIDGET = "appwidget";
- private static final String TAG_SHORTCUT = "shortcut";
- private static final String TAG_FOLDER = "folder";
- private static final String TAG_PARTNER_FOLDER = "partner-folder";
- private static final String TAG_EXTRA = "extra";
- private static final String TAG_INCLUDE = "include";
-
- // Style attrs -- "Favorite"
- private static final String ATTR_CLASS_NAME = "className";
- private static final String ATTR_PACKAGE_NAME = "packageName";
- private static final String ATTR_CONTAINER = "container";
- private static final String ATTR_SCREEN = "screen";
- private static final String ATTR_X = "x";
- private static final String ATTR_Y = "y";
- private static final String ATTR_SPAN_X = "spanX";
- private static final String ATTR_SPAN_Y = "spanY";
- private static final String ATTR_ICON = "icon";
- private static final String ATTR_TITLE = "title";
- private static final String ATTR_URI = "uri";
-
- // Style attrs -- "Include"
- private static final String ATTR_WORKSPACE = "workspace";
-
- // Style attrs -- "Extra"
- private static final String ATTR_KEY = "key";
- private static final String ATTR_VALUE = "value";
-
private final Context mContext;
- private final PackageManager mPackageManager;
private final AppWidgetHost mAppWidgetHost;
private long mMaxItemId = -1;
private long mMaxScreenId = -1;
@@ -431,7 +378,6 @@
DatabaseHelper(Context context) {
super(context, LauncherFiles.LAUNCHER_DB, null, DATABASE_VERSION);
mContext = context;
- mPackageManager = context.getPackageManager();
mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
// In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
@@ -787,8 +733,8 @@
}
// Add default hotseat icons
- loadFavorites(db, new SimpleWorkspaceLoader(this, mContext.getResources(),
- R.xml.update_workspace));
+ loadFavorites(db, new DefaultLayoutParser(mContext, mAppWidgetHost, this,
+ mContext.getResources(), R.xml.update_workspace));
version = 9;
}
@@ -1355,31 +1301,7 @@
return rank;
}
- private static final void beginDocument(XmlPullParser parser, String firstElementName)
- throws XmlPullParserException, IOException {
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- ;
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- if (!parser.getName().equals(firstElementName)) {
- throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
- ", expected " + firstElementName);
- }
- }
-
- private static Intent buildMainIntent() {
- Intent intent = new Intent(Intent.ACTION_MAIN, null);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- return intent;
- }
-
- private int loadFavorites(SQLiteDatabase db, WorkspaceLoader loader) {
+ private int loadFavorites(SQLiteDatabase db, AutoInstallsLayout loader) {
ArrayList<Long> screenIds = new ArrayList<Long>();
// TODO: Use multiple loaders with fall-back and transaction.
int count = loader.loadLayout(db, screenIds);
@@ -1406,389 +1328,6 @@
return count;
}
- /**
- * Loads the default set of favorite packages from an xml file.
- *
- * @param db The database to write the values into
- * @param filterContainerId The specific container id of items to load
- * @param the set of screenIds which are used by the favorites
- */
- private int loadFavoritesRecursive(SQLiteDatabase db, Resources res, int workspaceResourceId,
- ArrayList<Long> screenIds) {
-
- ContentValues values = new ContentValues();
- if (LOGD) Log.v(TAG, String.format("Loading favorites from resid=0x%08x", workspaceResourceId));
-
- int count = 0;
- try {
- XmlResourceParser parser = res.getXml(workspaceResourceId);
- beginDocument(parser, TAG_FAVORITES);
-
- final int depth = parser.getDepth();
-
- int type;
- while (((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- boolean added = false;
- final String name = parser.getName();
-
- if (TAG_INCLUDE.equals(name)) {
-
- final int resId = getAttributeResourceValue(parser, ATTR_WORKSPACE, 0);
-
- if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s<include workspace=%08x>"),
- "", resId));
-
- if (resId != 0 && resId != workspaceResourceId) {
- // recursively load some more favorites, why not?
- count += loadFavoritesRecursive(db, res, resId, screenIds);
- added = false;
- } else {
- Log.w(TAG, String.format("Skipping <include workspace=0x%08x>", resId));
- }
-
- if (LOGD) Log.v(TAG, String.format(("%" + (2*(depth+1)) + "s</include>"), ""));
- continue;
- }
-
- // Assuming it's a <favorite> at this point
- long container = LauncherSettings.Favorites.CONTAINER_DESKTOP;
- String strContainer = getAttributeValue(parser, ATTR_CONTAINER);
- if (strContainer != null) {
- container = Long.valueOf(strContainer);
- }
-
- String screen = getAttributeValue(parser, ATTR_SCREEN);
- String x = getAttributeValue(parser, ATTR_X);
- String y = getAttributeValue(parser, ATTR_Y);
-
- values.clear();
- values.put(LauncherSettings.Favorites.CONTAINER, container);
- values.put(LauncherSettings.Favorites.SCREEN, screen);
- values.put(LauncherSettings.Favorites.CELLX, x);
- values.put(LauncherSettings.Favorites.CELLY, y);
-
- if (LOGD) {
- final String title = getAttributeValue(parser, ATTR_TITLE);
- final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
- final String something = title != null ? title : pkg;
- Log.v(TAG, String.format(
- ("%" + (2*(depth+1)) + "s<%s%s c=%d s=%s x=%s y=%s>"),
- "", name,
- (something == null ? "" : (" \"" + something + "\"")),
- container, screen, x, y));
- }
-
- if (TAG_FAVORITE.equals(name)) {
- long id = addAppShortcut(db, values, parser);
- added = id >= 0;
- } else if (TAG_APPWIDGET.equals(name)) {
- added = addAppWidget(parser, type, db, values);
- } else if (TAG_SHORTCUT.equals(name)) {
- long id = addUriShortcut(db, values, res, parser);
- added = id >= 0;
- } else if (TAG_RESOLVE.equals(name)) {
- // This looks through the contained favorites (or meta-favorites) and
- // attempts to add them as shortcuts in the fallback group's location
- // until one is added successfully.
- added = false;
- final int groupDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > groupDepth) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final String fallback_item_name = parser.getName();
- if (!added) {
- if (TAG_FAVORITE.equals(fallback_item_name)) {
- final long id = addAppShortcut(db, values, parser);
- added = id >= 0;
- } else {
- Log.e(TAG, "Fallback groups can contain only favorites, found "
- + fallback_item_name);
- }
- }
- }
- } else if (TAG_FOLDER.equals(name)) {
- // Folder contents are nested in this XML file
- added = loadFolder(db, values, res, parser);
-
- } else if (TAG_PARTNER_FOLDER.equals(name)) {
- // Folder contents come from an external XML resource
- final Partner partner = Partner.get(mPackageManager);
- if (partner != null) {
- final Resources partnerRes = partner.getResources();
- final int resId = partnerRes.getIdentifier(Partner.RES_FOLDER,
- "xml", partner.getPackageName());
- if (resId != 0) {
- final XmlResourceParser partnerParser = partnerRes.getXml(resId);
- beginDocument(partnerParser, TAG_FOLDER);
- added = loadFolder(db, values, partnerRes, partnerParser);
- }
- }
- }
- if (added) {
- long screenId = Long.parseLong(screen);
- // Keep track of the set of screens which need to be added to the db.
- if (!screenIds.contains(screenId) &&
- container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- screenIds.add(screenId);
- }
- count++;
- }
- }
- } catch (XmlPullParserException e) {
- Log.w(TAG, "Got exception parsing favorites.", e);
- } catch (IOException e) {
- Log.w(TAG, "Got exception parsing favorites.", e);
- } catch (RuntimeException e) {
- Log.w(TAG, "Got exception parsing favorites.", e);
- }
- return count;
- }
-
- /**
- * Parse folder items starting at {@link XmlPullParser} location. Allow recursive
- * includes of items.
- */
- private void addToFolder(SQLiteDatabase db, Resources res, XmlResourceParser parser,
- ArrayList<Long> folderItems, long folderId) throws IOException, XmlPullParserException {
- int type;
- int folderDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > folderDepth) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final String tag = parser.getName();
-
- final ContentValues childValues = new ContentValues();
- childValues.put(LauncherSettings.Favorites.CONTAINER, folderId);
-
- if (LOGD) {
- final String pkg = getAttributeValue(parser, ATTR_PACKAGE_NAME);
- final String uri = getAttributeValue(parser, ATTR_URI);
- Log.v(TAG, String.format(("%" + (2*(folderDepth+1)) + "s<%s \"%s\">"), "",
- tag, uri != null ? uri : pkg));
- }
-
- if (TAG_FAVORITE.equals(tag) && folderId >= 0) {
- final long id = addAppShortcut(db, childValues, parser);
- if (id >= 0) {
- folderItems.add(id);
- }
- } else if (TAG_SHORTCUT.equals(tag) && folderId >= 0) {
- final long id = addUriShortcut(db, childValues, res, parser);
- if (id >= 0) {
- folderItems.add(id);
- }
- } else if (TAG_INCLUDE.equals(tag) && folderId >= 0) {
- addToFolder(db, res, parser, folderItems, folderId);
- } else {
- throw new RuntimeException("Folders can contain only shortcuts");
- }
- }
- }
-
- /**
- * Parse folder starting at current {@link XmlPullParser} location.
- */
- private boolean loadFolder(SQLiteDatabase db, ContentValues values, Resources res,
- XmlResourceParser parser) throws IOException, XmlPullParserException {
- final String title;
- final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
- if (titleResId != 0) {
- title = res.getString(titleResId);
- } else {
- title = mContext.getResources().getString(R.string.folder_name);
- }
-
- values.put(LauncherSettings.Favorites.TITLE, title);
- long folderId = addFolder(db, values);
- boolean added = folderId >= 0;
-
- ArrayList<Long> folderItems = new ArrayList<Long>();
- addToFolder(db, res, parser, folderItems, folderId);
-
- // We can only have folders with >= 2 items, so we need to remove the
- // folder and clean up if less than 2 items were included, or some
- // failed to add, and less than 2 were actually added
- if (folderItems.size() < 2 && folderId >= 0) {
- // Delete the folder
- deleteId(db, folderId);
-
- // If we have a single item, promote it to where the folder
- // would have been.
- if (folderItems.size() == 1) {
- final ContentValues childValues = new ContentValues();
- copyInteger(values, childValues, LauncherSettings.Favorites.CONTAINER);
- copyInteger(values, childValues, LauncherSettings.Favorites.SCREEN);
- copyInteger(values, childValues, LauncherSettings.Favorites.CELLX);
- copyInteger(values, childValues, LauncherSettings.Favorites.CELLY);
-
- final long id = folderItems.get(0);
- db.update(TABLE_FAVORITES, childValues,
- LauncherSettings.Favorites._ID + "=" + id, null);
- } else {
- added = false;
- }
- }
- return added;
- }
-
- // A meta shortcut attempts to resolve an intent specified as a URI in the XML, if a
- // logical choice for what shortcut should be used for that intent exists, then it is
- // added. Otherwise add nothing.
- private long addAppShortcutByUri(SQLiteDatabase db, ContentValues values,
- String intentUri) {
- Intent metaIntent;
- try {
- metaIntent = Intent.parseUri(intentUri, 0);
- } catch (URISyntaxException e) {
- Log.e(TAG, "Unable to add meta-favorite: " + intentUri, e);
- return -1;
- }
-
- ResolveInfo resolved = mPackageManager.resolveActivity(metaIntent,
- PackageManager.MATCH_DEFAULT_ONLY);
- final List<ResolveInfo> appList = mPackageManager.queryIntentActivities(
- metaIntent, PackageManager.MATCH_DEFAULT_ONLY);
-
- // Verify that the result is an app and not just the resolver dialog asking which
- // app to use.
- if (wouldLaunchResolverActivity(resolved, appList)) {
- // If only one of the results is a system app then choose that as the default.
- final ResolveInfo systemApp = getSingleSystemActivity(appList);
- if (systemApp == null) {
- // There is no logical choice for this meta-favorite, so rather than making
- // a bad choice just add nothing.
- Log.w(TAG, "No preference or single system activity found for "
- + metaIntent.toString());
- return -1;
- }
- resolved = systemApp;
- }
- final ActivityInfo info = resolved.activityInfo;
- final Intent intent = mPackageManager.getLaunchIntentForPackage(info.packageName);
- if (intent == null) {
- return -1;
- }
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(), intent);
- }
-
- private ResolveInfo getSingleSystemActivity(List<ResolveInfo> appList) {
- ResolveInfo systemResolve = null;
- final int N = appList.size();
- for (int i = 0; i < N; ++i) {
- try {
- ApplicationInfo info = mPackageManager.getApplicationInfo(
- appList.get(i).activityInfo.packageName, 0);
- if ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- if (systemResolve != null) {
- return null;
- } else {
- systemResolve = appList.get(i);
- }
- }
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Unable to get info about resolve results", e);
- return null;
- }
- }
- return systemResolve;
- }
-
- private boolean wouldLaunchResolverActivity(ResolveInfo resolved,
- List<ResolveInfo> appList) {
- // If the list contains the above resolved activity, then it can't be
- // ResolverActivity itself.
- for (int i = 0; i < appList.size(); ++i) {
- ResolveInfo tmp = appList.get(i);
- if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
- && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
- return false;
- }
- }
- return true;
- }
-
- private long addAppShortcut(SQLiteDatabase db, ContentValues values,
- XmlResourceParser parser) {
- final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
- final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
- final String uri = getAttributeValue(parser, ATTR_URI);
-
- if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) {
- ActivityInfo info;
- try {
- ComponentName cn;
- try {
- cn = new ComponentName(packageName, className);
- info = mPackageManager.getActivityInfo(cn, 0);
- } catch (PackageManager.NameNotFoundException nnfe) {
- String[] packages = mPackageManager.currentToCanonicalPackageNames(
- new String[] { packageName });
- cn = new ComponentName(packages[0], className);
- info = mPackageManager.getActivityInfo(cn, 0);
- }
- final Intent intent = buildMainIntent();
- intent.setComponent(cn);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- return addAppShortcut(db, values, info.loadLabel(mPackageManager).toString(),
- intent);
- } catch (PackageManager.NameNotFoundException e) {
- Log.w(TAG, "Unable to add favorite: " + packageName +
- "/" + className, e);
- }
- return -1;
- } else if (!TextUtils.isEmpty(uri)) {
- // If no component specified try to find a shortcut to add from the URI.
- return addAppShortcutByUri(db, values, uri);
- } else {
- Log.e(TAG, "Skipping invalid <favorite> with no component or uri");
- return -1;
- }
- }
-
- private long addAppShortcut(SQLiteDatabase db, ContentValues values, String title,
- Intent intent) {
- long id = generateNewItemId();
- values.put(Favorites.INTENT, intent.toUri(0));
- values.put(Favorites.TITLE, title);
- values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION);
- values.put(Favorites.SPANX, 1);
- values.put(Favorites.SPANY, 1);
- values.put(Favorites._ID, id);
- if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
- return -1;
- } else {
- return id;
- }
- }
-
- private long addFolder(SQLiteDatabase db, ContentValues values) {
- values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER);
- values.put(Favorites.SPANX, 1);
- values.put(Favorites.SPANY, 1);
- long id = generateNewItemId();
- values.put(Favorites._ID, id);
- if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) {
- return -1;
- } else {
- return id;
- }
- }
-
private ComponentName getSearchWidgetProvider() {
SearchManager searchManager =
(SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
@@ -1815,140 +1354,6 @@
return null;
}
- private boolean addAppWidget(XmlResourceParser parser, int type,
- SQLiteDatabase db, ContentValues values)
- throws XmlPullParserException, IOException {
-
- String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
- String className = getAttributeValue(parser, ATTR_CLASS_NAME);
-
- if (packageName == null || className == null) {
- return false;
- }
-
- boolean hasPackage = true;
- ComponentName cn = new ComponentName(packageName, className);
- try {
- mPackageManager.getReceiverInfo(cn, 0);
- } catch (Exception e) {
- String[] packages = mPackageManager.currentToCanonicalPackageNames(
- new String[] { packageName });
- cn = new ComponentName(packages[0], className);
- try {
- mPackageManager.getReceiverInfo(cn, 0);
- } catch (Exception e1) {
- System.out.println("Can't find widget provider: " + className);
- hasPackage = false;
- }
- }
-
- if (hasPackage) {
- String spanX = getAttributeValue(parser, ATTR_SPAN_X);
- String spanY = getAttributeValue(parser, ATTR_SPAN_Y);
-
- values.put(Favorites.SPANX, spanX);
- values.put(Favorites.SPANY, spanY);
-
- // Read the extras
- Bundle extras = new Bundle();
- int widgetDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > widgetDepth) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- if (TAG_EXTRA.equals(parser.getName())) {
- String key = getAttributeValue(parser, ATTR_KEY);
- String value = getAttributeValue(parser, ATTR_VALUE);
- if (key != null && value != null) {
- extras.putString(key, value);
- } else {
- throw new RuntimeException("Widget extras must have a key and value");
- }
- } else {
- throw new RuntimeException("Widgets can contain only extras");
- }
- }
-
- return addAppWidget(db, values, cn, extras);
- }
-
- return false;
- }
-
- private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn,
- Bundle extras) {
- boolean allocatedAppWidgets = false;
- final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
-
- try {
- int appWidgetId = mAppWidgetHost.allocateAppWidgetId();
-
- values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
- values.put(Favorites.APPWIDGET_ID, appWidgetId);
- values.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
- values.put(Favorites._ID, generateNewItemId());
- dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
-
- allocatedAppWidgets = true;
-
- // TODO: need to check return value
- appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn);
-
- // Send a broadcast to configure the widget
- if (extras != null && !extras.isEmpty()) {
- Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
- intent.setComponent(cn);
- intent.putExtras(extras);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- mContext.sendBroadcast(intent);
- }
- } catch (RuntimeException ex) {
- Log.e(TAG, "Problem allocating appWidgetId", ex);
- }
-
- return allocatedAppWidgets;
- }
-
- private long addUriShortcut(SQLiteDatabase db, ContentValues values, Resources res,
- XmlResourceParser parser) {
- final int iconResId = getAttributeResourceValue(parser, ATTR_ICON, 0);
- final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
-
- Intent intent;
- String uri = null;
- try {
- uri = getAttributeValue(parser, ATTR_URI);
- intent = Intent.parseUri(uri, 0);
- } catch (URISyntaxException e) {
- Log.w(TAG, "Shortcut has malformed uri: " + uri);
- return -1; // Oh well
- }
-
- if (iconResId == 0 || titleResId == 0) {
- Log.w(TAG, "Shortcut is missing title or icon resource ID");
- return -1;
- }
-
- long id = generateNewItemId();
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- values.put(Favorites.INTENT, intent.toUri(0));
- values.put(Favorites.TITLE, res.getString(titleResId));
- values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_SHORTCUT);
- values.put(Favorites.SPANX, 1);
- values.put(Favorites.SPANY, 1);
- values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
- values.put(Favorites.ICON_PACKAGE, res.getResourcePackageName(iconResId));
- values.put(Favorites.ICON_RESOURCE, res.getResourceName(iconResId));
- values.put(Favorites._ID, id);
-
- if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) {
- return -1;
- }
- return id;
- }
-
private void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
final ContentResolver resolver = mContext.getContentResolver();
Cursor c = null;
@@ -2248,38 +1653,6 @@
return selectWhere.toString();
}
- /**
- * Return attribute value, attempting launcher-specific namespace first
- * before falling back to anonymous attribute.
- */
- private static String getAttributeValue(XmlResourceParser parser, String attribute) {
- String value = parser.getAttributeValue(
- "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute);
- if (value == null) {
- value = parser.getAttributeValue(null, attribute);
- }
- return value;
- }
-
- /**
- * Return attribute resource value, attempting launcher-specific namespace
- * first before falling back to anonymous attribute.
- */
- private static int getAttributeResourceValue(XmlResourceParser parser, String attribute,
- int defaultValue) {
- int value = parser.getAttributeResourceValue(
- "http://schemas.android.com/apk/res-auto/com.android.launcher3", attribute,
- defaultValue);
- if (value == defaultValue) {
- value = parser.getAttributeResourceValue(null, attribute, defaultValue);
- }
- return value;
- }
-
- private static void copyInteger(ContentValues from, ContentValues to, String key) {
- to.put(key, from.getAsInteger(key));
- }
-
static class SqlArguments {
public final String table;
public final String where;
@@ -2311,29 +1684,4 @@
}
}
}
-
- static interface WorkspaceLoader {
- /**
- * @param screenIds A mutable list of screen its
- * @return the number of workspace items added.
- */
- int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds);
- }
-
- private static class SimpleWorkspaceLoader implements WorkspaceLoader {
- private final Resources mRes;
- private final int mWorkspaceId;
- private final DatabaseHelper mHelper;
-
- SimpleWorkspaceLoader(DatabaseHelper helper, Resources res, int workspaceId) {
- mHelper = helper;
- mRes = res;
- mWorkspaceId = workspaceId;
- }
-
- @Override
- public int loadLayout(SQLiteDatabase db, ArrayList<Long> screenIds) {
- return mHelper.loadFavoritesRecursive(db, mRes, mWorkspaceId, screenIds);
- }
- }
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 48fc0c9..7d65f46 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -204,6 +204,8 @@
protected boolean mAllowLongPress = true;
+ private boolean mWasInOverscroll = false;
+
// Page Indicator
private int mPageIndicatorViewId;
private PageIndicator mPageIndicator;
@@ -625,6 +627,7 @@
// a method that subclasses can override to add behavior
protected void onPageEndMoving() {
+ mWasInOverscroll = false;
}
/**
@@ -663,6 +666,7 @@
if (isXBeforeFirstPage) {
super.scrollTo(0, y);
if (mAllowOverScroll) {
+ mWasInOverscroll = true;
if (isRtl) {
overScroll(x - mMaxScrollX);
} else {
@@ -672,6 +676,7 @@
} else if (isXAfterLastPage) {
super.scrollTo(mMaxScrollX, y);
if (mAllowOverScroll) {
+ mWasInOverscroll = true;
if (isRtl) {
overScroll(x);
} else {
@@ -679,6 +684,10 @@
}
}
} else {
+ if (mWasInOverscroll) {
+ overScroll(0);
+ mWasInOverscroll = false;
+ }
mOverScrollX = x;
super.scrollTo(x, y);
}
@@ -1513,6 +1522,7 @@
mLastMotionXRemainder = 0;
mTouchX = getViewportOffsetX() + getScrollX();
mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
+ onScrollInteractionBegin();
pageBeginMoving();
}
}
@@ -1752,6 +1762,7 @@
mActivePointerId = ev.getPointerId(0);
if (mTouchState == TOUCH_STATE_SCROLLING) {
+ onScrollInteractionBegin();
pageBeginMoving();
}
break;
@@ -1940,6 +1951,7 @@
getScrollY(), vX, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
invalidate();
}
+ onScrollInteractionEnd();
} else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
// at this point we have not moved beyond the touch slop
// (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
@@ -2025,6 +2037,15 @@
mActivePointerId = INVALID_POINTER;
}
+ /**
+ * Triggered by scrolling via touch
+ */
+ protected void onScrollInteractionBegin() {
+ }
+
+ protected void onScrollInteractionEnd() {
+ }
+
protected void onUnhandledTap(MotionEvent ev) {
((Launcher) getContext()).onClick(this);
}
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index d23a330..179c60a 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -41,9 +41,9 @@
private final LauncherAppWidgetInfo mInfo;
private final int mStartState;
private final Intent mIconLookupIntent;
+ private final boolean mDisabledForSafeMode;
private Bitmap mIcon;
- private PreloadIconDrawable mDrawable;
private Drawable mCenterDrawable;
private Drawable mTopCornerDrawable;
@@ -53,11 +53,13 @@
private final TextPaint mPaint;
private Layout mSetupTextLayout;
- public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info) {
+ public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
+ boolean disabledForSafeMode) {
super(context);
mInfo = info;
mStartState = info.restoreStatus;
mIconLookupIntent = new Intent().setComponent(info.providerName);
+ mDisabledForSafeMode = disabledForSafeMode;
mPaint = new TextPaint();
mPaint.setColor(0xFFFFFFFF);
@@ -106,14 +108,21 @@
return;
}
mIcon = icon;
- if (mDrawable != null) {
- mDrawable.setCallback(null);
- mDrawable = null;
+ if (mCenterDrawable != null) {
+ mCenterDrawable.setCallback(null);
+ mCenterDrawable = null;
}
if (mIcon != null) {
- // The view displays two modes, one with a setup icon and another with a preload icon
- // in the center.
- if (isReadyForClickSetup()) {
+ // The view displays three modes,
+ // 1) App icon in the center
+ // 2) Preload icon in the center
+ // 3) Setup icon in the center and app icon in the top right corner.
+ if (mDisabledForSafeMode) {
+ FastBitmapDrawable disabledIcon = Utilities.createIconDrawable(mIcon);
+ disabledIcon.setGhostModeEnabled(true);
+ mCenterDrawable = disabledIcon;
+ mTopCornerDrawable = null;
+ } else if (isReadyForClickSetup()) {
mCenterDrawable = getResources().getDrawable(R.drawable.ic_setting);
mTopCornerDrawable = new FastBitmapDrawable(mIcon);
} else {
@@ -123,8 +132,9 @@
}
FastBitmapDrawable drawable = Utilities.createIconDrawable(mIcon);
- mDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
- mDrawable.setCallback(this);
+ mCenterDrawable = new PreloadIconDrawable(drawable, sPreloaderTheme);
+ mCenterDrawable.setCallback(this);
+ mTopCornerDrawable = null;
applyState();
}
mDrawableSizeChanged = true;
@@ -133,12 +143,12 @@
@Override
protected boolean verifyDrawable(Drawable who) {
- return (who == mDrawable) || super.verifyDrawable(who);
+ return (who == mCenterDrawable) || super.verifyDrawable(who);
}
public void applyState() {
- if (mDrawable != null) {
- mDrawable.setLevel(Math.max(mInfo.installProgress, 0));
+ if (mCenterDrawable != null) {
+ mCenterDrawable.setLevel(Math.max(mInfo.installProgress, 0));
}
}
@@ -158,23 +168,30 @@
@Override
protected void onDraw(Canvas canvas) {
- if (mDrawable != null) {
+ if (mCenterDrawable == null) {
+ // Nothing to draw
+ return;
+ }
+
+ if (mTopCornerDrawable == null) {
if (mDrawableSizeChanged) {
+ int outset = (mCenterDrawable instanceof PreloadIconDrawable) ?
+ ((PreloadIconDrawable) mCenterDrawable).getOutset() : 0;
int maxSize = LauncherAppState.getInstance().getDynamicGrid()
- .getDeviceProfile().iconSizePx + 2 * mDrawable.getOutset();
+ .getDeviceProfile().iconSizePx + 2 * outset;
int size = Math.min(maxSize, Math.min(
getWidth() - getPaddingLeft() - getPaddingRight(),
getHeight() - getPaddingTop() - getPaddingBottom()));
mRect.set(0, 0, size, size);
- mRect.inset(mDrawable.getOutset(), mDrawable.getOutset());
+ mRect.inset(outset, outset);
mRect.offsetTo((getWidth() - mRect.width()) / 2, (getHeight() - mRect.height()) / 2);
- mDrawable.setBounds(mRect);
+ mCenterDrawable.setBounds(mRect);
mDrawableSizeChanged = false;
}
-
- mDrawable.draw(canvas);
- } else if ((mCenterDrawable != null) && (mTopCornerDrawable != null)) {
+ mCenterDrawable.draw(canvas);
+ } else {
+ // Draw the top corner icon and "Setup" text is possible
if (mDrawableSizeChanged) {
DeviceProfile grid = getDeviceProfile();
int iconSize = grid.iconSizePx;
diff --git a/src/com/android/launcher3/SearchDropTargetBar.java b/src/com/android/launcher3/SearchDropTargetBar.java
index 435dbda..6205088 100644
--- a/src/com/android/launcher3/SearchDropTargetBar.java
+++ b/src/com/android/launcher3/SearchDropTargetBar.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -37,7 +38,7 @@
private static final int sTransitionOutDuration = 175;
private ObjectAnimator mDropTargetBarAnim;
- private ObjectAnimator mQSBSearchBarAnim;
+ private ValueAnimator mQSBSearchBarAnim;
private static final AccelerateInterpolator sAccelerateInterpolator =
new AccelerateInterpolator();
@@ -70,28 +71,38 @@
mInfoDropTarget.setLauncher(launcher);
mDeleteDropTarget.setLauncher(launcher);
mQSBSearchBar = launcher.getQsbBar();
- if (mEnableDropDownDropTargets) {
- mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
- -mBarHeight);
+ if (mQSBSearchBar != null) {
+ if (mEnableDropDownDropTargets) {
+ mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0,
+ -mBarHeight);
+ } else {
+ mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+ }
+ setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
} else {
- mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
+ // Create a no-op animation of the search bar is null
+ mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0);
+ mQSBSearchBarAnim.setDuration(sTransitionInDuration);
}
- setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
}
private void prepareStartAnimation(View v) {
// Enable the hw layers before the animation starts (will be disabled in the onAnimationEnd
// callback below)
- v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ if (v != null) {
+ v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
}
- private void setupAnimation(ObjectAnimator anim, final View v) {
+ private void setupAnimation(ValueAnimator anim, final View v) {
anim.setInterpolator(sAccelerateInterpolator);
anim.setDuration(sTransitionInDuration);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- v.setLayerType(View.LAYER_TYPE_NONE, null);
+ if (v != null) {
+ v.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
}
});
}
@@ -145,9 +156,9 @@
mQSBSearchBarAnim.reverse();
} else {
mQSBSearchBarAnim.cancel();
- if (mEnableDropDownDropTargets) {
+ if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
mQSBSearchBar.setTranslationY(0);
- } else {
+ } else if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(1f);
}
}
@@ -161,9 +172,9 @@
mQSBSearchBarAnim.start();
} else {
mQSBSearchBarAnim.cancel();
- if (mEnableDropDownDropTargets) {
+ if (mQSBSearchBar != null && mEnableDropDownDropTargets) {
mQSBSearchBar.setTranslationY(-mBarHeight);
- } else {
+ } else if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(0f);
}
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 92d7c7d..9cedae0 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -638,7 +638,7 @@
c.setBitmap(null);
}
// Render the icon
- Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info));
+ Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info.activityInfo));
int paddingTop = mContext.
getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2683bec..518ee97 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -67,6 +67,7 @@
import com.android.launcher3.FolderIcon.FolderRingAnimator;
import com.android.launcher3.Launcher.CustomContentCallbacks;
+import com.android.launcher3.Launcher.LauncherOverlay;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
@@ -289,6 +290,12 @@
private boolean mDeferDropAfterUninstall;
private boolean mUninstallSuccessful;
+ // State related to Launcher Overlay
+ LauncherOverlay mLauncherOverlay;
+ boolean mScrollInteractionBegan;
+ boolean mStartedSendingScrollEvents;
+ boolean mShouldSendPageSettled;
+
private final Runnable mBindPages = new Runnable() {
@Override
public void run() {
@@ -1249,6 +1256,58 @@
stripEmptyScreens();
mStripScreensOnPageStopMoving = false;
}
+
+ if (mShouldSendPageSettled) {
+ mLauncherOverlay.onScrollSettled();
+ mShouldSendPageSettled = false;
+ }
+ }
+
+ protected void onScrollInteractionBegin() {
+ super.onScrollInteractionEnd();
+ mScrollInteractionBegan = true;
+ }
+
+ protected void onScrollInteractionEnd() {
+ super.onScrollInteractionEnd();
+ mScrollInteractionBegan = false;
+ if (mStartedSendingScrollEvents) {
+ mStartedSendingScrollEvents = false;
+ mLauncherOverlay.onScrollInteractionEnd();
+ }
+ }
+
+ public void setLauncherOverlay(LauncherOverlay overlay) {
+ mLauncherOverlay = overlay;
+ }
+
+ @Override
+ protected void overScroll(float amount) {
+ boolean isRtl = isLayoutRtl();
+ boolean shouldOverScroll = (amount <= 0 && (!hasCustomContent() || isRtl)) ||
+ (amount >= 0 && (!hasCustomContent() || !isRtl));
+
+ boolean shouldScrollOverlay = (amount <= 0 && mLauncherOverlay != null && !isRtl) ||
+ (amount >= 0 && mLauncherOverlay != null && isRtl);
+
+ if (shouldScrollOverlay) {
+ if (!mStartedSendingScrollEvents && mScrollInteractionBegan) {
+ mStartedSendingScrollEvents = true;
+ mLauncherOverlay.onScrollInteractionBegin();
+ mShouldSendPageSettled = true;
+ }
+ int screenSize = getViewportWidth();
+ float f = (amount / screenSize);
+
+ int progress = (int) Math.abs((f * 100));
+
+ mLauncherOverlay.onScrollChange(progress, isRtl);
+ } else if (shouldOverScroll) {
+ dampedOverScroll(amount);
+ mOverScrollEffect = acceleratedOverFactor(amount);
+ } else {
+ mOverScrollEffect = 0;
+ }
}
@Override
@@ -1710,18 +1769,6 @@
}
}
- @Override
- protected void overScroll(float amount) {
- boolean shouldOverScroll = (amount < 0 && (!hasCustomContent() || isLayoutRtl())) ||
- (amount > 0 && (!hasCustomContent() || !isLayoutRtl()));
- if (shouldOverScroll) {
- dampedOverScroll(amount);
- mOverScrollEffect = acceleratedOverFactor(amount);
- } else {
- mOverScrollEffect = 0;
- }
- }
-
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mWindowToken = getWindowToken();
@@ -2353,10 +2400,6 @@
.alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
- Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
- .alpha(finalSearchBarAlpha).withLayer();
- searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
-
Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
.alpha(finalOverviewPanelAlpha).withLayer();
overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
@@ -2364,11 +2407,9 @@
// For animation optimations, we may need to provide the Launcher transition
// with a set of views on which to force build layers in certain scenarios.
hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (layerViews != null) {
layerViews.add(hotseat);
- layerViews.add(searchBar);
layerViews.add(overviewPanel);
}
@@ -2385,11 +2426,21 @@
overviewPanelAlpha.setDuration(duration);
pageIndicatorAlpha.setDuration(duration);
hotseatAlpha.setDuration(duration);
- searchBarAlpha.setDuration(duration);
+
+ if (searchBar != null) {
+ Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
+ .alpha(finalSearchBarAlpha).withLayer();
+ searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
+ searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ if (layerViews != null) {
+ layerViews.add(searchBar);
+ }
+ searchBarAlpha.setDuration(duration);
+ anim.play(searchBarAlpha);
+ }
anim.play(overviewPanelAlpha);
anim.play(hotseatAlpha);
- anim.play(searchBarAlpha);
anim.play(pageIndicatorAlpha);
anim.setStartDelay(delay);
} else {
@@ -4693,20 +4744,11 @@
removeItemsByComponentName(cns, user);
}
- // Removes items that match the application info specified, when applications are removed
- // as a part of an update, this is called to ensure that other widgets and application
- // shortcuts are not removed.
- void removeItemsByApplicationInfo(final ArrayList<AppInfo> appInfos, UserHandleCompat user) {
- // Just create a hash table of all the specific components that this will affect
- HashSet<ComponentName> cns = new HashSet<ComponentName>();
- for (AppInfo info : appInfos) {
- cns.add(info.componentName);
- }
-
- // Remove all the things
- removeItemsByComponentName(cns, user);
- }
-
+ /**
+ * Removes items that match the item info specified. When applications are removed
+ * as a part of an update, this is called to ensure that other widgets and application
+ * shortcuts are not removed.
+ */
void removeItemsByComponentName(final HashSet<ComponentName> componentNames,
final UserHandleCompat user) {
ArrayList<CellLayout> cellLayouts = getWorkspaceAndHotseatCellLayouts();
@@ -4827,7 +4869,6 @@
}
}
-
void updateShortcuts(ArrayList<ShortcutInfo> shortcuts) {
final HashSet<ShortcutInfo> updates = new HashSet<ShortcutInfo>(shortcuts);
mapOverItems(MAP_RECURSE, new ItemOperator() {
@@ -4835,9 +4876,12 @@
public boolean evaluate(ItemInfo info, View v, View parent) {
if (info instanceof ShortcutInfo && v instanceof BubbleTextView &&
updates.contains(info)) {
- ShortcutInfo shortcutInfo = (ShortcutInfo) info;
+ ShortcutInfo si = (ShortcutInfo) info;
BubbleTextView shortcut = (BubbleTextView) v;
- shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache, true, false);
+ boolean oldPromiseState = shortcut.getCompoundDrawables()[1]
+ instanceof PreloadIconDrawable;
+ shortcut.applyFromShortcutInfo(si, mIconCache, true,
+ si.isPromise() != oldPromiseState);
if (parent != null) {
parent.invalidate();
@@ -4849,125 +4893,6 @@
});
}
- void updateShortcutsAndWidgets(ArrayList<AppInfo> apps) {
- // Break the appinfo list per user
- final HashMap<UserHandleCompat, ArrayList<AppInfo>> appsPerUser =
- new HashMap<UserHandleCompat, ArrayList<AppInfo>>();
- for (AppInfo info : apps) {
- ArrayList<AppInfo> filtered = appsPerUser.get(info.user);
- if (filtered == null) {
- filtered = new ArrayList<AppInfo>();
- appsPerUser.put(info.user, filtered);
- }
- filtered.add(info);
- }
-
- for (Map.Entry<UserHandleCompat, ArrayList<AppInfo>> entry : appsPerUser.entrySet()) {
- updateShortcutsAndWidgetsPerUser(entry.getValue(), entry.getKey());
- }
- }
-
- private void updateShortcutsAndWidgetsPerUser(ArrayList<AppInfo> apps,
- final UserHandleCompat user) {
- // Create a map of the apps to test against
- final HashMap<ComponentName, AppInfo> appsMap = new HashMap<ComponentName, AppInfo>();
- final HashSet<String> pkgNames = new HashSet<String>();
- for (AppInfo ai : apps) {
- appsMap.put(ai.componentName, ai);
- pkgNames.add(ai.componentName.getPackageName());
- }
- final HashSet<ComponentName> iconsToRemove = new HashSet<ComponentName>();
-
- mapOverItems(MAP_RECURSE, new ItemOperator() {
- @Override
- public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
- ShortcutInfo shortcutInfo = (ShortcutInfo) info;
- ComponentName cn = shortcutInfo.getTargetComponent();
- AppInfo appInfo = appsMap.get(cn);
- if (user.equals(shortcutInfo.user) && cn != null
- && pkgNames.contains(cn.getPackageName())) {
- boolean promiseStateChanged = false;
- boolean infoUpdated = false;
- if (shortcutInfo.isPromise()) {
- if (shortcutInfo.hasStatusFlag(ShortcutInfo.FLAG_AUTOINTALL_ICON)) {
- // Auto install icon
- PackageManager pm = getContext().getPackageManager();
- ResolveInfo matched = pm.resolveActivity(
- new Intent(Intent.ACTION_MAIN)
- .setComponent(cn).addCategory(Intent.CATEGORY_LAUNCHER),
- PackageManager.MATCH_DEFAULT_ONLY);
- if (matched == null) {
- // Try to find the best match activity.
- Intent intent = pm.getLaunchIntentForPackage(
- cn.getPackageName());
- if (intent != null) {
- cn = intent.getComponent();
- appInfo = appsMap.get(cn);
- }
-
- if ((intent == null) || (appsMap == null)) {
- // Could not find a default activity. Remove this item.
- iconsToRemove.add(shortcutInfo.getTargetComponent());
-
- // process next shortcut.
- return false;
- }
- shortcutInfo.promisedIntent = intent;
- }
- }
-
- // Restore the shortcut.
- shortcutInfo.intent = shortcutInfo.promisedIntent;
- shortcutInfo.promisedIntent = null;
- shortcutInfo.status &= ~ShortcutInfo.FLAG_RESTORED_ICON
- & ~ShortcutInfo.FLAG_AUTOINTALL_ICON
- & ~ShortcutInfo.FLAG_INSTALL_SESSION_ACTIVE;
-
- promiseStateChanged = true;
- infoUpdated = true;
- shortcutInfo.updateIcon(mIconCache);
- LauncherModel.updateItemInDatabase(getContext(), shortcutInfo);
- }
-
- if ((shortcutInfo.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
- // Since package was just updated, the target must be available now.
- shortcutInfo.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
- infoUpdated = true;
- }
-
- // Only update the icon and labels if the shortcuts points to an app target
- if ((appInfo != null) && LauncherModel.isShortcutAppTarget(shortcutInfo)) {
- shortcutInfo.updateIcon(mIconCache);
- shortcutInfo.title = appInfo.title.toString();
- shortcutInfo.contentDescription = appInfo.contentDescription;
- infoUpdated = true;
- }
-
- if (infoUpdated) {
- BubbleTextView shortcut = (BubbleTextView) v;
- shortcut.applyFromShortcutInfo(shortcutInfo,
- mIconCache, true, promiseStateChanged);
-
- if (parent != null) {
- parent.invalidate();
- }
- }
- }
- }
- // process all the shortcuts
- return false;
- }
- });
-
- if (!iconsToRemove.isEmpty()) {
- removeItemsByComponentName(iconsToRemove, user);
- }
- if (user.equals(UserHandleCompat.myUserHandle())) {
- restorePendingWidgets(pkgNames);
- }
- }
-
public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
ArrayList<String> packages = new ArrayList<String>(1);
packages.add(packageName);
@@ -5008,9 +4933,11 @@
}
public void updatePackageState(ArrayList<PackageInstallInfo> installInfos) {
- HashSet<String> completedPackages = new HashSet<String>();
-
for (final PackageInstallInfo installInfo : installInfos) {
+ if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
+ continue;
+ }
+
mapOverItems(MAP_RECURSE, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View v, View parent) {
@@ -5038,42 +4965,10 @@
return false;
}
});
-
- if (installInfo.state == PackageInstallerCompat.STATUS_INSTALLED) {
- completedPackages.add(installInfo.packageName);
- }
- }
-
- // Note that package states are sent only for myUser
- if (!completedPackages.isEmpty()) {
- restorePendingWidgets(completedPackages);
}
}
- private void restorePendingWidgets(final Set<String> installedPackaged) {
- final ArrayList<LauncherAppWidgetInfo> changedInfo = new ArrayList<LauncherAppWidgetInfo>();
-
- // Iterate non recursively as widgets can't be inside a folder.
- mapOverItems(MAP_NO_RECURSE, new ItemOperator() {
-
- @Override
- public boolean evaluate(ItemInfo info, View v, View parent) {
- if (info instanceof LauncherAppWidgetInfo) {
- LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
- if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
- && installedPackaged.contains(widgetInfo.providerName.getPackageName())) {
-
- changedInfo.add(widgetInfo);
-
- // Remove the provider not ready flag
- widgetInfo.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
- LauncherModel.updateItemInDatabase(getContext(), widgetInfo);
- }
- }
- // process all the widget
- return false;
- }
- });
+ void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
if (!changedInfo.isEmpty()) {
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
mLauncher.getAppWidgetHost());
@@ -5083,6 +4978,13 @@
widgetRefresh.run();
} else {
// widgetRefresh will automatically run when the packages are updated.
+ // For now just update the progress bars
+ for (LauncherAppWidgetInfo info : changedInfo) {
+ if (info.hostView instanceof PendingAppWidgetHostView) {
+ info.installProgress = 100;
+ ((PendingAppWidgetHostView) info.hostView).applyState();
+ }
+ }
}
}
}