Merge "Launcher3: fix app shortcuts for suspended apps" into ub-launcher3-master
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 23ea195..86ae73e 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -76,6 +76,14 @@
android:process=":wallpaper_chooser">
</service>
+ <service android:name="com.android.launcher3.notification.NotificationListener"
+ android:enabled="@bool/notification_badging_enabled"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService" />
+ </intent-filter>
+ </service>
+
<meta-data android:name="android.nfc.disable_beam_default"
android:value="true" />
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6c5990d..418b3a3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -56,6 +56,7 @@
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher_home"
android:label="@string/derived_app_name"
+ android:theme="@style/LauncherTheme"
android:largeHeap="@bool/config_largeHeap"
android:restoreAnyVersion="true"
android:supportsRtl="true" >
@@ -69,7 +70,6 @@
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
- android:theme="@style/LauncherTheme"
android:windowSoftInputMode="adjustPan"
android:screenOrientation="nosensor"
android:configChanges="keyboard|keyboardHidden|navigation"
@@ -90,6 +90,7 @@
<activity
android:name="com.android.launcher3.SettingsActivity"
android:label="@string/settings_button_text"
+ android:theme="@android:style/Theme.DeviceDefault.Settings"
android:autoRemoveFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
diff --git a/res/drawable/all_apps_divider.xml b/res/drawable/all_apps_divider.xml
index 3fe5295..4bd274d 100644
--- a/res/drawable/all_apps_divider.xml
+++ b/res/drawable/all_apps_divider.xml
@@ -15,6 +15,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <solid android:color="@color/all_apps_divider_color" />
+ <solid android:color="?android:attr/colorControlHighlight" />
<size android:height="1dp" />
</shape>
\ No newline at end of file
diff --git a/res/drawable/all_apps_search_hint.xml b/res/drawable/all_apps_search_hint.xml
index 36a0f03..b2ff7a4 100644
--- a/res/drawable/all_apps_search_hint.xml
+++ b/res/drawable/all_apps_search_hint.xml
@@ -15,6 +15,6 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="#00FFFFFF" android:state_focused="true" />
+ <item android:color="@android:color/transparent" android:state_focused="true" />
<item android:color="?android:attr/colorAccent"/>
</selector>
\ No newline at end of file
diff --git a/res/drawable/bg_pill_focused.xml b/res/drawable/bg_pill_focused.xml
index 37afad0..54075d9 100644
--- a/res/drawable/bg_pill_focused.xml
+++ b/res/drawable/bg_pill_focused.xml
@@ -16,9 +16,8 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
- <shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <stroke android:color="#616161" android:width="2dp"/>
+ <shape android:shape="rectangle">
+ <stroke android:color="?android:attr/colorControlActivated" android:width="2dp" />
<corners android:radius="@dimen/bg_pill_radius" />
</shape>
</item>
diff --git a/res/drawable/deep_shortcuts_drag_handle.xml b/res/drawable/deep_shortcuts_drag_handle.xml
index 99d2b07..82e844d 100644
--- a/res/drawable/deep_shortcuts_drag_handle.xml
+++ b/res/drawable/deep_shortcuts_drag_handle.xml
@@ -18,9 +18,10 @@
android:width="@dimen/deep_shortcut_drag_handle_size"
android:height="@dimen/deep_shortcut_drag_handle_size"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/textColorHint" >
<path
android:pathData="M20 9H4v2h16V9zM4 15h16v-2H4v2z"
- android:fillColor="#4D000000"/>
+ android:fillColor="@android:color/white" />
</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_setting.xml b/res/drawable/ic_setting.xml
index 8a50c0c..e89c158 100644
--- a/res/drawable/ic_setting.xml
+++ b/res/drawable/ic_setting.xml
@@ -19,6 +19,6 @@
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="@color/workspace_icon_text_color"
android:pathData="M38.86 25.95c.08-.64 .14-1.29 .14-1.95s-.06-1.31-.14-1.95l4.23-3.31c.38-.3 .49-.84 .24-1.28l-4-6.93c-.25-.43-.77-.61-1.22-.43l-4.98 2.01c-1.03-.79-2.16-1.46-3.38-1.97L29 4.84c-.09-.47-.5-.84-1-.84h-8c-.5 0-.91 .37-.99 .84l-.75 5.3c-1.22 .51-2.35 1.17-3.38 1.97L9.9 10.1c-.45-.17-.97 0-1.22 .43l-4 6.93c-.25 .43-.14 .97 .24 1.28l4.22 3.31C9.06 22.69 9 23.34 9 24s.06 1.31 .14 1.95l-4.22 3.31c-.38 .3-.49 .84-.24 1.28l4 6.93c.25 .43 .77 .61 1.22 .43l4.98-2.01c1.03 .79 2.16 1.46 3.38 1.97l.75 5.3c.08 .47 .49 .84 .99 .84h8c.5 0 .91-.37 .99-.84l.75-5.3c1.22-.51 2.35-1.17 3.38-1.97l4.98 2.01c.45 .17 .97 0 1.22-.43l4-6.93c.25-.43 .14-.97-.24-1.28l-4.22-3.31zM24 31c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/>
</vector>
diff --git a/res/drawable/ic_wallpaper.xml b/res/drawable/ic_wallpaper.xml
index 7af4b2a..b7fcfbf 100644
--- a/res/drawable/ic_wallpaper.xml
+++ b/res/drawable/ic_wallpaper.xml
@@ -19,6 +19,6 @@
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="@color/workspace_icon_text_color"
android:pathData="M8 8h14V4H8C5.79 4 4 5.79 4 8v14h4V8zm12 18l-8 10h24l-6-8-4.06 5.42L20 26zm14-9c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3 3-1.34 3-3zm6-13H26v4h14v14h4V8c0-2.21-1.79-4-4-4zm0 36H26v4h14c2.21 0 4-1.79 4-4V26h-4v14zM8 26H4v14c0 2.21 1.79 4 4 4h14v-4H8V26z"/>
</vector>
diff --git a/res/drawable/ic_widget.xml b/res/drawable/ic_widget.xml
index 3e7bd7b..97706e3 100644
--- a/res/drawable/ic_widget.xml
+++ b/res/drawable/ic_widget.xml
@@ -19,6 +19,6 @@
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="@color/workspace_icon_text_color"
android:pathData="M26 26v16h16V26H26zM6 42h16V26H6v16zM6 6v16h16V6H6zm27.31-2.63L22 14.69 33.31 26l11.31-11.31L33.31 3.37z"/>
</vector>
diff --git a/res/drawable/quantum_panel.xml b/res/drawable/quantum_panel.xml
deleted file mode 100644
index fda1003..0000000
--- a/res/drawable/quantum_panel.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:drawable="@drawable/quantum_panel_shape"
- android:insetBottom="@dimen/quantum_panel_outer_padding"
- android:insetLeft="@dimen/quantum_panel_outer_padding"
- android:insetRight="@dimen/quantum_panel_outer_padding"
- android:insetTop="@dimen/quantum_panel_outer_padding" />
diff --git a/res/drawable/quantum_panel_shape.xml b/res/drawable/quantum_panel_shape.xml
deleted file mode 100644
index 1083615..0000000
--- a/res/drawable/quantum_panel_shape.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/quantum_panel_bg_color" />
- <corners
- android:radius="2dp" />
-</shape>
\ No newline at end of file
diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml
index 5f5b38b..d6bdac2 100644
--- a/res/layout/all_apps.xml
+++ b/res/layout/all_apps.xml
@@ -22,7 +22,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- launcher:revealBackground="@drawable/quantum_panel_shape">
+ launcher:revealBackground="@drawable/round_rect_primary">
<View
android:id="@+id/reveal_view"
@@ -54,8 +54,7 @@
android:descendantFocusability="afterDescendants"
android:focusable="true"
android:paddingStart="@dimen/container_fastscroll_thumb_max_width"
- android:paddingEnd="@dimen/container_fastscroll_thumb_max_width"
- android:theme="@style/AllAppsOverscroll" />
+ android:paddingEnd="@dimen/container_fastscroll_thumb_max_width" />
<!-- Fast scroller popup -->
<TextView
@@ -87,7 +86,7 @@
android:maxLines="1"
android:scrollHorizontally="true"
android:singleLine="true"
- android:textColor="#4c4c4c"
+ android:textColor="?android:attr/textColorSecondary"
android:hint="@string/all_apps_search_bar_hint"
android:textColorHint="@drawable/all_apps_search_hint"
android:textSize="16sp" />
@@ -95,11 +94,11 @@
</com.android.launcher3.allapps.AllAppsRecyclerViewContainerView>
<View
+ style="@style/AllAppsNavBarProtection"
android:id="@+id/nav_bar_bg"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="bottom"
- android:background="@color/all_apps_navbar_color"
android:focusable="false"
android:visibility="invisible" />
</com.android.launcher3.allapps.AllAppsContainerView>
\ No newline at end of file
diff --git a/res/layout/all_apps_button.xml b/res/layout/all_apps_button.xml
index 68cc109..4bc780a 100644
--- a/res/layout/all_apps_button.xml
+++ b/res/layout/all_apps_button.xml
@@ -14,6 +14,4 @@
limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/Icon"
- android:focusable="true" />
+<TextView style="@style/BaseIcon" />
diff --git a/res/layout/all_apps_empty_search.xml b/res/layout/all_apps_empty_search.xml
index e1635d6..463adac 100644
--- a/res/layout/all_apps_empty_search.xml
+++ b/res/layout/all_apps_empty_search.xml
@@ -25,7 +25,6 @@
android:paddingRight="16dp"
android:fontFamily="sans-serif-medium"
android:textSize="14sp"
- android:textColor="#212121"
- android:alpha="0.56"
+ android:textColor="?android:attr/textColorTertiary"
android:focusable="false" />
diff --git a/res/layout/all_apps_icon.xml b/res/layout/all_apps_icon.xml
index 3d4bef7..1e83041 100644
--- a/res/layout/all_apps_icon.xml
+++ b/res/layout/all_apps_icon.xml
@@ -16,12 +16,13 @@
<com.android.launcher3.BubbleTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:launcher="http://schemas.android.com/apk/res-auto"
- style="@style/Icon.AllApps"
+ style="@style/BaseIcon"
android:id="@+id/icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:focusable="true"
launcher:iconDisplay="all_apps"
- launcher:centerVertically="true" />
+ launcher:centerVertically="true"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp"
+ android:drawablePadding="@dimen/dynamic_grid_icon_drawable_padding" />
diff --git a/res/layout/app_icon.xml b/res/layout/app_icon.xml
index 831cee5..fa6eb89 100644
--- a/res/layout/app_icon.xml
+++ b/res/layout/app_icon.xml
@@ -14,6 +14,4 @@
limitations under the License.
-->
-<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/Icon"
- android:focusable="true" />
+<com.android.launcher3.BubbleTextView style="@style/BaseIcon.Workspace" />
diff --git a/res/layout/deep_shortcut.xml b/res/layout/deep_shortcut.xml
index 1f67682..6c1d4da 100644
--- a/res/layout/deep_shortcut.xml
+++ b/res/layout/deep_shortcut.xml
@@ -16,18 +16,28 @@
<com.android.launcher3.shortcuts.DeepShortcutView
xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="@dimen/bg_pill_width"
android:layout_height="@dimen/bg_pill_height"
android:elevation="@dimen/deep_shortcuts_elevation"
- android:background="@drawable/bg_white_pill">
+ android:background="@drawable/bg_white_pill" >
-<com.android.launcher3.shortcuts.DeepShortcutTextView
+ <com.android.launcher3.shortcuts.DeepShortcutTextView
+ style="@style/BaseIcon"
android:id="@+id/deep_shortcut"
- style="@style/Icon.DeepShortcut"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:focusable="true"
- android:background="@drawable/bg_pill_focused" />
+ android:background="@drawable/bg_pill_focused"
+ android:gravity="start|center_vertical"
+ android:textAlignment="viewStart"
+ android:paddingStart="@dimen/bg_pill_height"
+ android:paddingEnd="@dimen/deep_shortcut_padding_end"
+ android:drawableEnd="@drawable/deep_shortcuts_drag_handle"
+ android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
+ android:textSize="14sp"
+ android:fontFamily="sans-serif"
+ launcher:layoutHorizontal="true"
+ launcher:iconDisplay="shortcut_popup"
+ launcher:iconSizeOverride="@dimen/deep_shortcut_icon_size"
+ android:elevation="@dimen/deep_shortcuts_elevation" />
<View
android:id="@+id/popup_item_icon"
diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml
index 4d00331..de861a0 100644
--- a/res/layout/folder_application.xml
+++ b/res/layout/folder_application.xml
@@ -14,6 +14,9 @@
limitations under the License.
-->
-<com.android.launcher3.BubbleTextView xmlns:android="http://schemas.android.com/apk/res/android"
- style="@style/Icon.Folder"
- android:focusable="true" />
+<com.android.launcher3.BubbleTextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ style="@style/BaseIcon"
+ android:includeFontPadding="false"
+ launcher:iconDisplay="folder" />
diff --git a/res/layout/folder_icon.xml b/res/layout/folder_icon.xml
index 9eb8c9a..ccc6b01 100644
--- a/res/layout/folder_icon.xml
+++ b/res/layout/folder_icon.xml
@@ -21,8 +21,9 @@
android:orientation="vertical"
android:focusable="true" >
<com.android.launcher3.BubbleTextView
- style="@style/Icon"
+ style="@style/BaseIcon.Workspace"
android:id="@+id/folder_icon_name"
+ android:focusable="false"
android:layout_gravity="top"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/res/layout/notification_main.xml b/res/layout/notification_main.xml
index efb74b0..84827f1 100644
--- a/res/layout/notification_main.xml
+++ b/res/layout/notification_main.xml
@@ -21,7 +21,6 @@
android:layout_height="match_parent"
android:orientation="horizontal"
android:focusable="true"
- android:background="@drawable/bg_pill_focused"
android:elevation="@dimen/notification_elevation" >
<View
@@ -39,13 +38,20 @@
android:gravity="center_vertical">
<TextView
android:id="@+id/title"
- style="@style/Icon.DeepNotification"
+ android:textAlignment="viewStart"
+ android:fontFamily="sans-serif"
+ android:textSize="14sp"
+ android:textColor="?android:attr/textColorSecondary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text"
- style="@style/Icon.DeepNotification.SubText"
+ android:paddingEnd="4dp"
+ android:textSize="12sp"
+ android:textAlignment="viewStart"
+ android:fontFamily="sans-serif"
+ android:textColor="?android:attr/textColorTertiary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
diff --git a/res/layout/qsb_default_view.xml b/res/layout/qsb_default_view.xml
index 82bdea5..3075f80 100644
--- a/res/layout/qsb_default_view.xml
+++ b/res/layout/qsb_default_view.xml
@@ -23,7 +23,7 @@
android:layout_height="48dp"
android:layout_margin="16dp"
android:layout_gravity="center_vertical"
- android:background="@drawable/quantum_panel_shape"
+ android:background="@drawable/round_rect_primary"
android:elevation="2dp"
android:orientation="horizontal">
@@ -35,7 +35,7 @@
android:gravity="center_vertical"
android:paddingStart="16dp"
android:text="@string/abandoned_search"
- android:textColor="@color/quantum_panel_text_color"
+ android:textColor="?android:attr/textColorSecondary"
android:textAppearance="?android:textAppearanceMedium"
android:clickable="true"
android:background="?android:attr/selectableItemBackground" />
@@ -46,7 +46,7 @@
android:visibility="gone"
android:layout_height="match_parent"
android:src="@drawable/ic_setting"
- android:tint="@color/quantum_panel_text_color"
+ android:tint="?android:attr/textColorSecondary"
android:contentDescription="@string/gadget_setup_text"
android:padding="8dp"
android:background="?android:attr/selectableItemBackground" />
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index da2a861..cde6540 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -18,7 +18,7 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@drawable/quantum_panel"
+ android:background="@drawable/round_rect_primary"
android:elevation="5dp"
android:orientation="vertical" >
@@ -46,7 +46,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
- android:background="#00000000"
+ android:background="@android:color/transparent"
android:fontFamily="sans-serif-condensed"
android:gravity="center_horizontal"
android:hint="@string/folder_hint_text"
@@ -54,10 +54,10 @@
android:paddingBottom="@dimen/folder_label_padding_bottom"
android:paddingTop="@dimen/folder_label_padding_top"
android:singleLine="true"
- android:textColor="#ff777777"
+ android:textColor="?android:attr/textColorTertiary"
android:includeFontPadding="false"
- android:textColorHighlight="#ffCCCCCC"
- android:textColorHint="#ff808080"
+ android:textColorHighlight="?android:attr/colorControlHighlight"
+ android:textColorHint="?android:attr/textColorHint"
android:textSize="@dimen/folder_label_text_size" />
<com.android.launcher3.pageindicators.PageIndicatorDots
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index a8af201..2063f32 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -18,7 +18,7 @@
xmlns:launcher="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@drawable/quantum_panel"
+ android:background="@drawable/round_rect_primary"
android:elevation="5dp"
android:orientation="vertical" >
@@ -46,7 +46,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
- android:background="#00000000"
+ android:background="@android:color/transparent"
android:fontFamily="sans-serif-condensed"
android:textStyle="bold"
android:gravity="center_horizontal"
@@ -55,9 +55,9 @@
android:paddingBottom="@dimen/folder_label_padding_bottom"
android:paddingTop="@dimen/folder_label_padding_top"
android:singleLine="true"
- android:textColor="#EE777777"
- android:textColorHighlight="#ffCCCCCC"
- android:textColorHint="#ff808080"
+ android:textColor="?android:attr/textColorTertiary"
+ android:textColorHighlight="?android:attr/colorControlHighlight"
+ android:textColorHint="?android:attr/textColorHint"
android:textSize="@dimen/folder_label_text_size" />
<com.android.launcher3.pageindicators.PageIndicatorDots
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 2e0f926..6137f03 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -98,7 +98,7 @@
<string name="action_move_screen_left" msgid="8854216831569401665">"স্ক্রীন বাঁ দিকে সরান"</string>
<string name="action_move_screen_right" msgid="329334910274311123">"স্ক্রীন ডান দিকে সরান"</string>
<string name="screen_moved" msgid="266230079505650577">"স্ক্রীন সরানো হয়েছে"</string>
- <string name="action_resize" msgid="1802976324781771067">"পুনরায় আকার দিন"</string>
+ <string name="action_resize" msgid="1802976324781771067">"আবার আকার দিন"</string>
<string name="action_increase_width" msgid="8773715375078513326">"প্রস্থ বাড়ান"</string>
<string name="action_increase_height" msgid="459390020612501122">"উচ্চতা বাড়ান"</string>
<string name="action_decrease_width" msgid="1374549771083094654">"প্রস্থ কমান"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index bcc1699..85b50c8 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -27,7 +27,7 @@
<string name="safemode_shortcut_error" msgid="9160126848219158407">"다운로드한 앱은 안전 모드에서 사용할 수 없습니다."</string>
<string name="safemode_widget_error" msgid="4863470563535682004">"안전 모드에서 위젯 사용 중지됨"</string>
<string name="shortcut_not_available" msgid="2536503539825726397">"바로가기를 사용할 수 없음"</string>
- <string name="home_screen" msgid="806512411299847073">"메인 스크린"</string>
+ <string name="home_screen" msgid="806512411299847073">"홈 화면"</string>
<string name="custom_actions" msgid="3747508247759093328">"맞춤 작업"</string>
<string name="long_press_widget_to_add" msgid="7699152356777458215">"위젯을 선택하려면 길게 터치하세요."</string>
<string name="long_accessible_way_to_add" msgid="4289502106628154155">"위젯을 선택하려면 두 번 탭한 다음 길게 터치하거나 맞춤 액션을 사용합니다."</string>
@@ -58,7 +58,7 @@
<string name="disabled_app_label" msgid="6673129024321402780">"<xliff:g id="APP_NAME">%1$s</xliff:g> 사용 안함"</string>
<string name="default_scroll_format" msgid="7475544710230993317">"페이지 %1$d/%2$d"</string>
<string name="workspace_scroll_format" msgid="8458889198184077399">"홈 화면 %1$d/%2$d"</string>
- <string name="workspace_new_page" msgid="257366611030256142">"새로운 메인 스크린 페이지"</string>
+ <string name="workspace_new_page" msgid="257366611030256142">"새로운 홈 화면 페이지"</string>
<string name="folder_opened" msgid="94695026776264709">"폴더 열림(<xliff:g id="WIDTH">%1$d</xliff:g>X<xliff:g id="HEIGHT">%2$d</xliff:g>)"</string>
<string name="folder_tap_to_close" msgid="4625795376335528256">"탭하여 폴더 닫기"</string>
<string name="folder_tap_to_rename" msgid="4017685068016979677">"탭하여 변경된 이름 저장"</string>
@@ -70,7 +70,7 @@
<string name="settings_button_text" msgid="8119458837558863227">"설정"</string>
<string name="msg_disabled_by_admin" msgid="6898038085516271325">"관리자가 사용 중지함"</string>
<string name="accessibility_action_overview" msgid="6257665857640347026">"개요"</string>
- <string name="allow_rotation_title" msgid="7728578836261442095">"메인 스크린 회전 허용"</string>
+ <string name="allow_rotation_title" msgid="7728578836261442095">"홈 화면 회전 허용"</string>
<string name="allow_rotation_desc" msgid="8662546029078692509">"휴대전화 회전 시"</string>
<string name="allow_rotation_blocked_desc" msgid="3212602545192996253">"현재 표시 설정에는 회전 기능이 허용되지 않습니다."</string>
<string name="package_state_unknown" msgid="7592128424511031410">"알 수 없음"</string>
@@ -80,9 +80,9 @@
<string name="abandoned_promise_explanation" msgid="3990027586878167529">"이 아이콘의 앱이 설치되어 있지 않습니다. 아이콘을 삭제하거나 앱을 검색하여 수동으로 설치하세요."</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> 다운로드 중, <xliff:g id="PROGRESS">%2$s</xliff:g> 완료"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> 설치 대기 중"</string>
- <string name="action_add_to_workspace" msgid="8902165848117513641">"메인 스크린에 추가"</string>
+ <string name="action_add_to_workspace" msgid="8902165848117513641">"홈 화면에 추가"</string>
<string name="action_move_here" msgid="2170188780612570250">"여기에 항목을 이동"</string>
- <string name="item_added_to_workspace" msgid="4211073925752213539">"메인 스크린에 항목 추가됨"</string>
+ <string name="item_added_to_workspace" msgid="4211073925752213539">"홈 화면에 항목 추가됨"</string>
<string name="item_removed" msgid="851119963877842327">"항목 삭제됨"</string>
<string name="action_move" msgid="4339390619886385032">"항목 이동"</string>
<string name="move_to_empty_cell" msgid="2833711483015685619">"<xliff:g id="NUMBER_0">%1$s</xliff:g>행 <xliff:g id="NUMBER_1">%2$s</xliff:g>열로 이동"</string>
@@ -94,7 +94,7 @@
<string name="added_to_folder" msgid="4793259502305558003">"항목이 폴더에 추가되었습니다."</string>
<string name="create_folder_with" msgid="4050141361160214248">"다음이 포함된 폴더 만들기: <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_created" msgid="6409794597405184510">"폴더를 만들었습니다."</string>
- <string name="action_move_to_workspace" msgid="1603837886334246317">"메인 스크린으로 이동"</string>
+ <string name="action_move_to_workspace" msgid="1603837886334246317">"홈 화면으로 이동"</string>
<string name="action_move_screen_left" msgid="8854216831569401665">"화면을 왼쪽으로 이동"</string>
<string name="action_move_screen_right" msgid="329334910274311123">"화면을 오른쪽으로 이동"</string>
<string name="screen_moved" msgid="266230079505650577">"화면 이동됨"</string>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 4589450..c97eaa2 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -77,7 +77,7 @@
<string name="abandoned_clean_this" msgid="7610119707847920412">"हटाउनुहोस्"</string>
<string name="abandoned_search" msgid="891119232568284442">"खोजी गर्नुहोस्"</string>
<string name="abandoned_promises_title" msgid="7096178467971716750">"यो अनुप्रयोग स्थापित छैन"</string>
- <string name="abandoned_promise_explanation" msgid="3990027586878167529">"यो प्रतिमाका लागि अनुप्रयोगलाई स्थापना गरिएको छैन। तपाईँ यसलाई हटाउन, वा अनुप्रयोग खोजी र स्वयं यो स्थापित गर्न सक्नुहुन्छ।"</string>
+ <string name="abandoned_promise_explanation" msgid="3990027586878167529">"यो प्रतिमाका लागि अनुप्रयोगलाई स्थापना गरिएको छैन। तपाईं यसलाई हटाउन, वा अनुप्रयोग खोजी र स्वयं यो स्थापित गर्न सक्नुहुन्छ।"</string>
<string name="app_downloading_title" msgid="8336702962104482644">"<xliff:g id="NAME">%1$s</xliff:g> डाउनलोड गर्दै, <xliff:g id="PROGRESS">%2$s</xliff:g> सम्पन्न"</string>
<string name="app_waiting_download_title" msgid="7053938513995617849">"<xliff:g id="NAME">%1$s</xliff:g> स्थापना गर्न प्रतीक्षा गर्दै"</string>
<string name="action_add_to_workspace" msgid="8902165848117513641">"गृह स्क्रिनमा थप्नुहोस्"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 907de79..bedef80 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -60,8 +60,8 @@
<string name="workspace_scroll_format" msgid="8458889198184077399">"Startskärmen %1$d av %2$d"</string>
<string name="workspace_new_page" msgid="257366611030256142">"Ny sida på startskärmen"</string>
<string name="folder_opened" msgid="94695026776264709">"Mappen är öppen, <xliff:g id="WIDTH">%1$d</xliff:g> gånger <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
- <string name="folder_tap_to_close" msgid="4625795376335528256">"Tryck om du vill stänga mappen"</string>
- <string name="folder_tap_to_rename" msgid="4017685068016979677">"Tryck om du vill spara namnändringen"</string>
+ <string name="folder_tap_to_close" msgid="4625795376335528256">"Tryck för att stänga mappen"</string>
+ <string name="folder_tap_to_rename" msgid="4017685068016979677">"Tryck för att spara namnändringen"</string>
<string name="folder_closed" msgid="4100806530910930934">"Mappen är stängd"</string>
<string name="folder_renamed" msgid="1794088362165669656">"Mappen har bytt namn till <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="folder_name_format" msgid="6629239338071103179">"Mapp: <xliff:g id="NAME">%1$s</xliff:g>"</string>
diff --git a/res/values-sw720dp/styles.xml b/res/values-sw720dp/styles.xml
index 674edaa..de809b1 100644
--- a/res/values-sw720dp/styles.xml
+++ b/res/values-sw720dp/styles.xml
@@ -25,6 +25,7 @@
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionModeOverlay">true</item>
+ <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
</style>
<!-- Workspace -->
diff --git a/res/values-v25/bools.xml b/res/values-v25/bools.xml
new file mode 100644
index 0000000..6f7ecd9
--- /dev/null
+++ b/res/values-v25/bools.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <!-- TODO(b/35443111): remove from v25 and keep in v26 -->
+ <bool name="notification_badging_enabled">true</bool>
+</resources>
\ No newline at end of file
diff --git a/res/values-v26/bools.xml b/res/values-v26/bools.xml
new file mode 100644
index 0000000..1093f78
--- /dev/null
+++ b/res/values-v26/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <bool name="notification_badging_enabled">true</bool>
+</resources>
\ No newline at end of file
diff --git a/res/values-v26/styles.xml b/res/values-v26/styles.xml
index 6877623..cb18409 100644
--- a/res/values-v26/styles.xml
+++ b/res/values-v26/styles.xml
@@ -21,4 +21,11 @@
<style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
<item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
</style>
+
+ <!-- From O and above, we show a dark nav bar in all-apps -->
+ <style name="AllAppsNavBarProtection">
+ <item name="android:alpha">0.6</item>
+ <item name="android:background">?android:attr/colorPrimary</item>
+ </style>
+
</resources>
diff --git a/res/values/bools.xml b/res/values/bools.xml
new file mode 100644
index 0000000..cc4a7ba
--- /dev/null
+++ b/res/values/bools.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+ <bool name="notification_badging_enabled">false</bool>
+</resources>
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index d166a79..a02df16 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -26,21 +26,11 @@
<color name="focused_background">#80c6c5c5</color>
<color name="workspace_icon_text_color">#FFF</color>
-
<color name="workspace_edge_effect_color">#FFFFFFFF</color>
- <color name="folder_edge_effect_color">#FF757575</color>
- <color name="page_indicator_dot_color">#FFDDDDDD</color>
- <color name="quantum_panel_text_color">#FF666666</color>
- <color name="quantum_panel_bg_color">#FFF5F5F5</color>
+ <color name="default_shadow_color_no_alpha">#FF000000</color>
<color name="outline_color">#FFFFFFFF</color>
- <color name="all_apps_divider_color">#1E000000</color>
- <color name="all_apps_caret_color">#FFFFFFFF</color>
- <color name="all_apps_caret_shadow_color">#22000000</color>
- <color name="all_apps_container_color">#FFF2F2F2</color>
- <color name="all_apps_navbar_color">#28000000</color>
- <color name="all_apps_light_navbar_color">#AAF2F2F2</color>
<color name="spring_loaded_panel_color">#40FFFFFF</color>
<color name="spring_loaded_highlighted_panel_border_color">#FFF</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 70f5b32..517bf9f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -89,6 +89,7 @@
<dimen name="widget_preview_key_shadow_distance">1dp</dimen>
<dimen name="widget_preview_corner_radius">2dp</dimen>
<dimen name="widget_preview_cell_divider_width">0.5dp</dimen>
+ <dimen name="widget_preview_shortcut_padding">8dp</dimen>
<dimen name="widget_section_height">56dp</dimen>
<dimen name="widget_section_icon_size">40dp</dimen>
@@ -120,9 +121,6 @@
<dimen name="spring_loaded_panel_border">1dp</dimen>
-<!-- Theme -->
- <dimen name="quantum_panel_outer_padding">4dp</dimen>
-
<!-- Folders -->
<!-- The size of the padding on the preview background drawable -->
<dimen name="folder_preview_padding">6dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a6f44f6..c1280c7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -53,9 +53,9 @@
<!-- Accessibility spoken message format for the dimensions of a widget in the drawer -->
<string name="widget_accessible_dims_format">%1$d wide by %2$d high</string>
<!-- Message to tell the user to press and hold a widget/icon to add it -->
- <string name="add_item_request_drag_hint" translatable="false">Touch & hold to place on home screen</string>
+ <string name="add_item_request_drag_hint">Touch & hold to place on home screen</string>
<!-- Button label to automatically add icon on home screen [CHAR_LIMIT=50] -->
- <string name="place_automatically" translatable="false">Place automatically</string>
+ <string name="place_automatically">Place automatically</string>
<!-- All Apps -->
<!-- Search bar text in the apps view. [CHAR_LIMIT=50] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 879c7d8..8a46e83 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -24,11 +24,17 @@
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowNoTitle">true</item>
+ <item name="android:colorEdgeEffect">#FF757575</item>
</style>
<style name="LauncherTheme" parent="@style/BaseLauncherTheme"></style>
- <style name="Theme" parent="@style/LauncherTheme"></style>
+ <!-- Theme for the widget container. Overridden on API 26. -->
+ <style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
+ <item name="android:colorEdgeEffect">?android:attr/textColorSecondaryInverse</item>
+ <item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textColorSecondary">?android:attr/textColorSecondaryInverse</item>
+ </style>
<style name="FastScrollerPopup" >
<item name="android:background">@drawable/container_fastscroll_popup_bg</item>
@@ -44,88 +50,35 @@
<item name="android:includeFontPadding">false</item>
</style>
- <!-- Theme for the widget container. Overridden on API 25. -->
- <style name="WidgetContainerTheme" parent="@android:style/Theme.DeviceDefault.Settings">
- <item name="android:colorEdgeEffect">@color/workspace_edge_effect_color</item>
- <item name="android:textColorPrimary">?android:attr/textColorPrimaryInverse</item>
- <item name="android:textColorSecondary">?android:attr/textColorSecondaryInverse</item>
+ <!-- Style for nav bar background in all-apps screen -->
+ <style name="AllAppsNavBarProtection">
+ <item name="android:alpha">?android:attr/spotShadowAlpha</item>
+ <item name="android:background">@color/default_shadow_color_no_alpha</item>
</style>
- <!-- Overscroll effect -->
- <style name="AllAppsOverscroll" parent="@android:style/Theme.DeviceDefault.Light">
- <item name="android:colorEdgeEffect">@color/folder_edge_effect_color</item>
- </style>
-
- <!-- Different icons -->
- <style name="Icon">
+ <!-- Base theme for BubbleTextView and sub classes -->
+ <style name="BaseIcon">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_gravity">center</item>
+ <item name="android:focusable">true</item>
<item name="android:gravity">center_horizontal</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">marquee</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:fontFamily">sans-serif-condensed</item>
+
+ <!-- No shadows in the base theme -->
+ <item name="android:shadowRadius">0</item>
+ <item name="customShadows">false</item>
+ </style>
+
+ <!-- Icon displayed on the worksapce -->
+ <style name="BaseIcon.Workspace">
+ <item name="customShadows">true</item>
<item name="android:textColor">@color/workspace_icon_text_color</item>
<item name="android:shadowRadius">2.0</item>
<item name="android:shadowColor">#B0000000</item>
- <item name="android:fontFamily">sans-serif-condensed</item>
- </style>
-
- <style name="Icon.AllApps">
- <item name="android:background">@null</item>
- <item name="android:textColor">@color/quantum_panel_text_color</item>
- <item name="android:drawablePadding">@dimen/dynamic_grid_icon_drawable_padding</item>
- <item name="android:shadowRadius">0</item>
- <item name="android:paddingLeft">4dp</item>
- <item name="android:paddingRight">4dp</item>
- <item name="customShadows">false</item>
- </style>
-
- <style name="Icon.Folder">
- <item name="android:background">@null</item>
- <item name="android:textColor">@color/quantum_panel_text_color</item>
- <item name="android:shadowRadius">0</item>
- <item name="android:gravity">center_horizontal</item>
- <item name="android:includeFontPadding">false</item>
- <item name="customShadows">false</item>
- <item name="iconDisplay">folder</item>
- </style>
-
- <style name="Icon.DeepShortcut">
- <item name="android:gravity">start|center_vertical</item>
- <item name="android:textAlignment">viewStart</item>
- <item name="android:elevation">@dimen/deep_shortcuts_elevation</item>
- <item name="android:paddingStart">@dimen/bg_pill_height</item>
- <item name="android:paddingEnd">@dimen/deep_shortcut_padding_end</item>
- <item name="android:drawableEnd">@drawable/deep_shortcuts_drag_handle</item>
- <item name="android:drawablePadding">@dimen/deep_shortcut_drawable_padding</item>
- <item name="android:textColor">#FF212121</item>
- <item name="android:textSize">14sp</item>
- <item name="android:fontFamily">sans-serif</item>
- <item name="android:shadowRadius">0</item>
- <item name="customShadows">false</item>
- <item name="layoutHorizontal">true</item>
- <item name="iconDisplay">shortcut_popup</item>
- <item name="iconSizeOverride">@dimen/deep_shortcut_icon_size</item>
- </style>
-
- <style name="Icon.DeepNotification">
- <item name="android:gravity">start</item>
- <item name="android:textAlignment">viewStart</item>
- <item name="android:elevation">@dimen/deep_shortcuts_elevation</item>
- <item name="android:textColor">#FF212121</item>
- <item name="android:textSize">14sp</item>
- <item name="android:fontFamily">sans-serif</item>
- <item name="android:shadowRadius">0</item>
- <item name="customShadows">false</item>
- <item name="layoutHorizontal">true</item>
- <item name="iconDisplay">shortcut_popup</item>
- <item name="iconSizeOverride">@dimen/deep_shortcut_icon_size</item>
- </style>
-
- <style name="Icon.DeepNotification.SubText">
- <item name="android:textColor">#FF757575</item>
- <item name="android:textSize">12sp</item>
- <item name="android:paddingEnd">4dp</item>
</style>
<!-- Drop targets -->
@@ -133,11 +86,11 @@
<item name="android:drawablePadding">7.5dp</item>
<item name="android:paddingLeft">16dp</item>
<item name="android:paddingRight">16dp</item>
- <item name="android:textColor">#FFFFFFFF</item>
+ <item name="android:textColor">@color/workspace_icon_text_color</item>
<item name="android:textSize">@dimen/drop_target_text_size</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
- <item name="android:shadowColor">#FF000000</item>
+ <item name="android:shadowColor">@color/default_shadow_color_no_alpha</item>
<item name="android:shadowDx">0.0</item>
<item name="android:shadowDy">1.0</item>
<item name="android:shadowRadius">4.0</item>
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index 4fecc3d..ba7c3f8 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -29,6 +29,7 @@
import android.widget.TextView;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.Themes;
/**
* The track and scrollbar that shows when you scroll the list.
@@ -102,7 +103,7 @@
mThumbPaint = new Paint();
mThumbPaint.setAntiAlias(true);
- mThumbPaint.setColor(Utilities.getColorAccent(rv.getContext()));
+ mThumbPaint.setColor(Themes.getColorAccent(rv.getContext()));
mThumbPaint.setStyle(Paint.Style.FILL);
mWidth = mMinWidth = res.getDimensionPixelSize(R.dimen.container_fastscroll_thumb_min_width);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index bbf2cb8..1a41e08 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -113,7 +113,7 @@
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.BubbleTextView, defStyle, 0);
- mCustomShadowsEnabled = a.getBoolean(R.styleable.BubbleTextView_customShadows, true);
+ mCustomShadowsEnabled = a.getBoolean(R.styleable.BubbleTextView_customShadows, false);
mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
mDeferShadowGenerationOnTouch =
a.getBoolean(R.styleable.BubbleTextView_deferShadowGeneration, false);
@@ -395,7 +395,7 @@
}
// If text is transparent, don't draw any shadow
- if (getCurrentTextColor() == getResources().getColor(android.R.color.transparent)) {
+ if ((getCurrentTextColor() >> 24) == 0) {
getPaint().clearShadowLayer();
super.draw(canvas);
return;
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 0df8e5a..e0fcbf0 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -50,6 +50,7 @@
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
import com.android.launcher3.accessibility.FolderAccessibilityHelper;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.DragPreviewProvider;
@@ -2097,12 +2098,13 @@
}
setInitialAnimationValues(true);
- a = new LauncherViewPropertyAnimator(child)
- .scaleX(initScale)
- .scaleY(initScale)
- .translationX(initDeltaX)
- .translationY(initDeltaY)
- .setDuration(REORDER_ANIMATION_DURATION);
+ a = LauncherAnimUtils.ofPropertyValuesHolder(child,
+ new PropertyListBuilder()
+ .scale(initScale)
+ .translationX(initDeltaX)
+ .translationY(initDeltaY)
+ .build())
+ .setDuration(REORDER_ANIMATION_DURATION);
a.setInterpolator(new android.view.animation.DecelerateInterpolator(1.5f));
a.start();
}
@@ -2144,7 +2146,7 @@
info.spanY = lp.cellVSpan;
if (requiresDbUpdate) {
- LauncherModel.modifyItemInDatabase(getContext(), info, container, screenId,
+ mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
info.cellX, info.cellY, info.spanX, info.spanY);
}
}
diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java
index 5fff2e7..2c69d0a 100644
--- a/src/com/android/launcher3/FolderInfo.java
+++ b/src/com/android/launcher3/FolderInfo.java
@@ -16,9 +16,9 @@
package com.android.launcher3;
-import android.content.Context;
import android.os.Process;
+import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.util.ContentWriter;
import java.util.ArrayList;
@@ -128,17 +128,17 @@
/**
* @param option flag to set or clear
* @param isEnabled whether to set or clear the flag
- * @param context if not null, save changes to the db.
+ * @param writer if not null, save changes to the db.
*/
- public void setOption(int option, boolean isEnabled, Context context) {
+ public void setOption(int option, boolean isEnabled, ModelWriter writer) {
int oldOptions = options;
if (isEnabled) {
options |= option;
} else {
options &= ~option;
}
- if (context != null && oldOptions != options) {
- LauncherModel.updateItemInDatabase(context, this);
+ if (writer != null && oldOptions != options) {
+ writer.updateItemInDatabase(this);
}
}
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 4a8a272..47052a7 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -25,7 +25,6 @@
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
@@ -40,6 +39,7 @@
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
+import com.android.launcher3.util.Themes;
public class Hotseat extends FrameLayout
implements UserEventDispatcher.LogContainerProvider {
@@ -70,7 +70,7 @@
mLauncher = Launcher.getLauncher(context);
mHasVerticalHotseat = mLauncher.getDeviceProfile().isVerticalBarLayout();
mBackgroundColor = ColorUtils.setAlphaComponent(
- ContextCompat.getColor(context, R.color.all_apps_container_color), 0);
+ Themes.getAttrColor(context, android.R.attr.colorPrimary), 0);
mBackground = new ColorDrawable(mBackgroundColor);
setBackground(mBackground);
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 6e9820c..1f473a2 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -27,7 +27,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
@@ -45,7 +44,6 @@
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
@@ -56,6 +54,7 @@
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.SQLiteCacheHelper;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import java.util.Collections;
@@ -132,10 +131,9 @@
IconProvider.class, context, R.string.icon_provider_class);
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper());
- mActivityBgColor = context.getResources().getColor(R.color.quantum_panel_bg_color);
- mPackageBgColor = Utilities.getAttrColor(
- new ContextThemeWrapper(context, R.style.WidgetContainerTheme),
- android.R.attr.colorPrimary);
+ mActivityBgColor = Themes.getColorPrimary(context, R.style.LauncherTheme);
+ mPackageBgColor = Themes.getColorPrimary(context, R.style.WidgetContainerTheme);
+
mLowResOptions = new BitmapFactory.Options();
// Always prefer RGB_565 config for low res. If the bitmap has transparency, it will
// automatically be loaded as ALPHA_8888.
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index d831a3a..34adf47 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -25,6 +25,7 @@
import android.widget.Toast;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.util.Themes;
public class InfoDropTarget extends UninstallDropTarget {
@@ -42,7 +43,7 @@
protected void onFinishInflate() {
super.onFinishInflate();
// Get the hover color
- mHoverColor = Utilities.getColorAccent(getContext());
+ mHoverColor = Themes.getColorAccent(getContext());
setDrawable(R.drawable.ic_info_launcher);
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index e3c6965..8aeab87 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -29,6 +29,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
@@ -187,6 +188,23 @@
}
}
+ public void dumpDisplayInfo(Context context) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ Point smallestSize = new Point();
+ Point largestSize = new Point();
+ display.getCurrentSizeRange(smallestSize, largestSize);
+
+ FileLog.e("DisplayInfo", "Default Density: " + DisplayMetrics.DENSITY_DEFAULT);
+ FileLog.e("DisplayInfo", "Density: " + dm.densityDpi);
+ FileLog.e("DisplayInfo", "Smallest size: " + smallestSize);
+ FileLog.e("DisplayInfo", "Largest size: " + largestSize);
+ FileLog.e("DisplayInfo", "minWidth/Height DPS: " + minWidthDps + ", " + minHeightDps);
+ }
+
ArrayList<InvariantDeviceProfile> getPredefinedDeviceProfiles(Context context) {
ArrayList<InvariantDeviceProfile> profiles = new ArrayList<>();
try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a160c41..14b9c82 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -85,6 +85,7 @@
import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.allapps.DefaultAppSearchController;
import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.compat.AppWidgetManagerCompat;
@@ -254,6 +255,7 @@
private ViewOnDrawExecutor mPendingExecutor;
private LauncherModel mModel;
+ private ModelWriter mModelWriter;
private IconCache mIconCache;
private ExtractedColors mExtractedColors;
private LauncherAccessibilityDelegate mAccessibilityDelegate;
@@ -371,6 +373,7 @@
mSharedPrefs = Utilities.getPrefs(this);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mModel = app.setLauncher(this);
+ mModelWriter = mModel.getWriter(mDeviceProfile.isVerticalBarLayout());
mIconCache = app.getIconCache();
mAccessibilityDelegate = new LauncherAccessibilityDelegate(this);
@@ -1498,7 +1501,7 @@
return;
}
- LauncherModel.addItemToDatabase(this, info, container, screenId, cellXY[0], cellXY[1]);
+ getModelWriter().addItemToDatabase(info, container, screenId, cellXY[0], cellXY[1]);
mWorkspace.addInScreen(view, info);
}
@@ -1526,7 +1529,7 @@
launcherInfo.minSpanY = itemInfo.minSpanY;
launcherInfo.user = appWidgetInfo.getUser();
- LauncherModel.addItemToDatabase(this, launcherInfo,
+ getModelWriter().addItemToDatabase(launcherInfo,
itemInfo.container, itemInfo.screenId, itemInfo.cellX, itemInfo.cellY);
if (hostView == null) {
@@ -1686,6 +1689,10 @@
return mModel;
}
+ public ModelWriter getModelWriter() {
+ return mModelWriter;
+ }
+
public SharedPreferences getSharedPrefs() {
return mSharedPrefs;
}
@@ -2127,8 +2134,7 @@
folderInfo.title = getText(R.string.folder_name);
// Update the model
- LauncherModel.addItemToDatabase(Launcher.this, folderInfo, container, screenId,
- cellX, cellY);
+ getModelWriter().addItemToDatabase(folderInfo, container, screenId, cellX, cellY);
// Create the view
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this, layout, folderInfo);
@@ -2156,7 +2162,7 @@
mWorkspace.removeWorkspaceItem(v);
}
if (deleteFromDb) {
- LauncherModel.deleteItemFromDatabase(this, itemInfo);
+ getModelWriter().deleteItemFromDatabase(itemInfo);
}
} else if (itemInfo instanceof FolderInfo) {
final FolderInfo folderInfo = (FolderInfo) itemInfo;
@@ -2165,7 +2171,7 @@
}
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
- LauncherModel.deleteFolderAndContentsFromDatabase(this, folderInfo);
+ getModelWriter().deleteFolderAndContentsFromDatabase(folderInfo);
}
} else if (itemInfo instanceof LauncherAppWidgetInfo) {
final LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) itemInfo;
@@ -2194,7 +2200,7 @@
}
}.executeOnExecutor(Utilities.THREAD_POOL_EXECUTOR);
}
- LauncherModel.deleteItemFromDatabase(this, widgetInfo);
+ getModelWriter().deleteItemFromDatabase(widgetInfo);
}
@Override
@@ -3373,7 +3379,7 @@
throw (new RuntimeException(desc));
} else {
Log.d(TAG, desc);
- LauncherModel.deleteItemFromDatabase(this, item);
+ getModelWriter().deleteItemFromDatabase(item);
continue;
}
}
@@ -3470,7 +3476,7 @@
+ " belongs to component " + item.providerName
+ ", as the provider is null");
}
- LauncherModel.deleteItemFromDatabase(this, item);
+ getModelWriter().deleteItemFromDatabase(item);
return;
}
@@ -3517,14 +3523,14 @@
: LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
}
- LauncherModel.updateItemInDatabase(this, item);
+ getModelWriter().updateItemInDatabase(item);
}
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
&& (appWidgetInfo.configure == null)) {
// The widget was marked as UI not ready, but there is no configure activity to
// update the UI.
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
- LauncherModel.updateItemInDatabase(this, item);
+ getModelWriter().updateItemInDatabase(item);
}
}
@@ -3574,7 +3580,7 @@
info.restoreStatus = finalRestoreFlag;
mWorkspace.reinflateWidgetsIfNecessary();
- LauncherModel.updateItemInDatabase(this, info);
+ getModelWriter().updateItemInDatabase(info);
return info;
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4dc5a97..e0e53a6 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,9 +16,11 @@
package com.android.launcher3;
+import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Looper;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -26,31 +28,46 @@
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.dynamicui.ExtractionUtils;
-import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.model.GridSizeMigrationTask;
import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TestingUtils;
-import com.android.launcher3.util.Thunk;
-import java.lang.ref.WeakReference;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
public class LauncherAppState {
public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD;
- @Thunk final LauncherModel mModel;
- private final IconCache mIconCache;
- private final WidgetPreviewLoader mWidgetCache;
-
- private static WeakReference<LauncherProvider> sLauncherProvider;
- private static Context sContext;
-
+ // We do not need any synchronization for this variable as its only written on UI thread.
private static LauncherAppState INSTANCE;
- private InvariantDeviceProfile mInvariantDeviceProfile;
+ private final Context mContext;
+ private final LauncherModel mModel;
+ private final IconCache mIconCache;
+ private final WidgetPreviewLoader mWidgetCache;
+ private final InvariantDeviceProfile mInvariantDeviceProfile;
- public static LauncherAppState getInstance(Context context) {
+
+ public static LauncherAppState getInstance(final Context context) {
if (INSTANCE == null) {
- INSTANCE = new LauncherAppState();
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ INSTANCE = new LauncherAppState(context.getApplicationContext());
+ GridSizeMigrationTask.logDeviceProfileIfChanged(
+ INSTANCE.getInvariantDeviceProfile(), context);
+ } else {
+ try {
+ return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
+ @Override
+ public LauncherAppState call() throws Exception {
+ return LauncherAppState.getInstance(context);
+ }
+ }).get();
+ } catch (InterruptedException|ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
return INSTANCE;
}
@@ -60,42 +77,30 @@
}
public Context getContext() {
- return sContext;
+ return mContext;
}
- static void setLauncherProvider(LauncherProvider provider) {
- if (sLauncherProvider != null) {
- Log.w(Launcher.TAG, "setLauncherProvider called twice! old=" +
- sLauncherProvider.get() + " new=" + provider);
+ private LauncherAppState(Context context) {
+ if (getLocalProvider(context) == null) {
+ throw new RuntimeException(
+ "Initializing LauncherAppState in the absence of LauncherProvider");
}
- sLauncherProvider = new WeakReference<>(provider);
-
- // The content provider exists for the entire duration of the launcher main process and
- // is the first component to get created. Initializing application context here ensures
- // that LauncherAppState always exists in the main process.
- sContext = provider.getContext().getApplicationContext();
- FileLog.setDir(sContext.getFilesDir());
- }
-
- private LauncherAppState() {
- if (sContext == null) {
- throw new IllegalStateException("LauncherAppState initiated before app context set");
- }
-
Log.v(Launcher.TAG, "LauncherAppState initiated");
+ Preconditions.assertUIThread();
+ mContext = context;
if (TestingUtils.MEMORY_DUMP_ENABLED) {
- TestingUtils.startTrackingMemory(sContext);
+ TestingUtils.startTrackingMemory(mContext);
}
- mInvariantDeviceProfile = new InvariantDeviceProfile(sContext);
- mIconCache = new IconCache(sContext, mInvariantDeviceProfile);
- mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache);
+ mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
+ mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
+ mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(this, mIconCache,
- Utilities.getOverrideObject(AppFilter.class, sContext, R.string.app_filter_class));
+ Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class));
- LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel);
+ LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
// Register intent receivers
IntentFilter filter = new IntentFilter();
@@ -112,21 +117,21 @@
filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
}
- sContext.registerReceiver(mModel, filter);
- UserManagerCompat.getInstance(sContext).enableAndResetCache();
- new ConfigMonitor(sContext).register();
+ mContext.registerReceiver(mModel, filter);
+ UserManagerCompat.getInstance(mContext).enableAndResetCache();
+ new ConfigMonitor(mContext).register();
- ExtractionUtils.startColorExtractionServiceIfNecessary(sContext);
+ ExtractionUtils.startColorExtractionServiceIfNecessary(mContext);
}
/**
* Call from Application.onTerminate(), which is not guaranteed to ever be called.
*/
public void onTerminate() {
- sContext.unregisterReceiver(mModel);
- final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
+ mContext.unregisterReceiver(mModel);
+ final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
launcherApps.removeOnAppsChangedCallback(mModel);
- PackageInstallerCompat.getInstance(sContext).onStop();
+ PackageInstallerCompat.getInstance(mContext).onStop();
}
/**
@@ -139,7 +144,7 @@
}
LauncherModel setLauncher(Launcher launcher) {
- sLauncherProvider.get().setLauncherProviderChangeListener(launcher);
+ getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
mModel.initialize(launcher);
return mModel;
}
@@ -166,4 +171,11 @@
public static InvariantDeviceProfile getIDP(Context context) {
return LauncherAppState.getInstance(context).getInvariantDeviceProfile();
}
+
+ private static LauncherProvider getLocalProvider(Context context) {
+ try (ContentProviderClient cl = context.getContentResolver()
+ .acquireContentProviderClient(LauncherProvider.AUTHORITY)) {
+ return (LauncherProvider) cl.getLocalContentProvider();
+ }
+ }
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 4d48fea..5fd5081 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -56,6 +56,7 @@
import com.android.launcher3.model.ExtendedModelTask;
import com.android.launcher3.model.GridSizeMigrationTask;
import com.android.launcher3.model.LoaderCursor;
+import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.model.PackageInstallStateChangedTask;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.model.PackageUpdatedTask;
@@ -264,19 +265,8 @@
enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
}
- /**
- * Adds an item to the DB if it was not created previously, or move it to a new
- * <container, screen, cellX, cellY>
- */
- public static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
- long screenId, int cellX, int cellY) {
- if (item.container == ItemInfo.NO_ID) {
- // From all apps
- addItemToDatabase(context, item, container, screenId, cellX, cellY);
- } else {
- // From somewhere else
- moveItemInDatabase(context, item, container, screenId, cellX, cellY);
- }
+ public ModelWriter getWriter(boolean hasVerticalHotseat) {
+ return new ModelWriter(mApp.getContext(), sBgDataModel, hasVerticalHotseat);
}
static void checkItemInfoLocked(
@@ -330,281 +320,6 @@
runOnWorkerThread(r);
}
- static void updateItemInDatabaseHelper(Context context, final ContentWriter writer,
- final ItemInfo item, final String callingFunction) {
- final long itemId = item.id;
- final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
- final ContentResolver cr = context.getContentResolver();
-
- final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
- final Context appContext = context.getApplicationContext();
- Runnable r = new Runnable() {
- public void run() {
- cr.update(uri, writer.getValues(appContext), null, null);
- updateItemArrays(item, itemId, stackTrace);
- }
- };
- runOnWorkerThread(r);
- }
-
- static void updateItemsInDatabaseHelper(Context context, final ArrayList<ContentValues> valuesList,
- final ArrayList<ItemInfo> items, final String callingFunction) {
- final ContentResolver cr = context.getContentResolver();
-
- final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
- Runnable r = new Runnable() {
- public void run() {
- ArrayList<ContentProviderOperation> ops =
- new ArrayList<ContentProviderOperation>();
- int count = items.size();
- for (int i = 0; i < count; i++) {
- ItemInfo item = items.get(i);
- final long itemId = item.id;
- final Uri uri = LauncherSettings.Favorites.getContentUri(itemId);
- ContentValues values = valuesList.get(i);
-
- ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
- updateItemArrays(item, itemId, stackTrace);
-
- }
- try {
- cr.applyBatch(LauncherProvider.AUTHORITY, ops);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- };
- runOnWorkerThread(r);
- }
-
- static void updateItemArrays(ItemInfo item, long itemId, StackTraceElement[] stackTrace) {
- // Lock on mBgLock *after* the db operation
- synchronized (sBgDataModel) {
- checkItemInfoLocked(itemId, item, stackTrace);
-
- if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP &&
- item.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- // Item is in a folder, make sure this folder exists
- if (!sBgDataModel.folders.containsKey(item.container)) {
- // An items container is being set to a that of an item which is not in
- // the list of Folders.
- String msg = "item: " + item + " container being set to: " +
- item.container + ", not in the list of folders";
- Log.e(TAG, msg);
- }
- }
-
- // Items are added/removed from the corresponding FolderInfo elsewhere, such
- // as in Workspace.onDrop. Here, we just add/remove them from the list of items
- // that are on the desktop, as appropriate
- ItemInfo modelItem = sBgDataModel.itemsIdMap.get(itemId);
- if (modelItem != null &&
- (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
- modelItem.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT)) {
- switch (modelItem.itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
- case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
- if (!sBgDataModel.workspaceItems.contains(modelItem)) {
- sBgDataModel.workspaceItems.add(modelItem);
- }
- break;
- default:
- break;
- }
- } else {
- sBgDataModel.workspaceItems.remove(modelItem);
- }
- }
- }
-
- /**
- * Move an item in the DB to a new <container, screen, cellX, cellY>
- */
- public static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
- final long screenId, final int cellX, final int cellY) {
- item.container = container;
- item.cellX = cellX;
- item.cellY = cellY;
-
- // We store hotseat items in canonical form which is this orientation invariant position
- // in the hotseat
- if (context instanceof Launcher && screenId < 0 &&
- container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screenId = Launcher.getLauncher(context).getHotseat()
- .getOrderInHotseat(cellX, cellY);
- } else {
- item.screenId = screenId;
- }
-
- final ContentWriter writer = new ContentWriter(context)
- .put(LauncherSettings.Favorites.CONTAINER, item.container)
- .put(LauncherSettings.Favorites.CELLX, item.cellX)
- .put(LauncherSettings.Favorites.CELLY, item.cellY)
- .put(LauncherSettings.Favorites.RANK, item.rank)
- .put(LauncherSettings.Favorites.SCREEN, item.screenId);
-
- updateItemInDatabaseHelper(context, writer, item, "moveItemInDatabase");
- }
-
- /**
- * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the
- * cellX, cellY have already been updated on the ItemInfos.
- */
- public static void moveItemsInDatabase(Context context, final ArrayList<ItemInfo> items,
- final long container, final int screen) {
-
- ArrayList<ContentValues> contentValues = new ArrayList<ContentValues>();
- int count = items.size();
-
- for (int i = 0; i < count; i++) {
- ItemInfo item = items.get(i);
- item.container = container;
-
- // We store hotseat items in canonical form which is this orientation invariant position
- // in the hotseat
- if (context instanceof Launcher && screen < 0 &&
- container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screenId = Launcher.getLauncher(context).getHotseat().getOrderInHotseat(item.cellX,
- item.cellY);
- } else {
- item.screenId = screen;
- }
-
- final ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites.CONTAINER, item.container);
- values.put(LauncherSettings.Favorites.CELLX, item.cellX);
- values.put(LauncherSettings.Favorites.CELLY, item.cellY);
- values.put(LauncherSettings.Favorites.RANK, item.rank);
- values.put(LauncherSettings.Favorites.SCREEN, item.screenId);
-
- contentValues.add(values);
- }
- updateItemsInDatabaseHelper(context, contentValues, items, "moveItemInDatabase");
- }
-
- /**
- * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>
- */
- static void modifyItemInDatabase(Context context, final ItemInfo item, final long container,
- final long screenId, final int cellX, final int cellY, final int spanX, final int spanY) {
- item.container = container;
- item.cellX = cellX;
- item.cellY = cellY;
- item.spanX = spanX;
- item.spanY = spanY;
-
- // We store hotseat items in canonical form which is this orientation invariant position
- // in the hotseat
- if (context instanceof Launcher && screenId < 0 &&
- container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screenId = Launcher.getLauncher(context).getHotseat()
- .getOrderInHotseat(cellX, cellY);
- } else {
- item.screenId = screenId;
- }
-
- final ContentWriter writer = new ContentWriter(context)
- .put(LauncherSettings.Favorites.CONTAINER, item.container)
- .put(LauncherSettings.Favorites.CELLX, item.cellX)
- .put(LauncherSettings.Favorites.CELLY, item.cellY)
- .put(LauncherSettings.Favorites.RANK, item.rank)
- .put(LauncherSettings.Favorites.SPANX, item.spanX)
- .put(LauncherSettings.Favorites.SPANY, item.spanY)
- .put(LauncherSettings.Favorites.SCREEN, item.screenId);
-
- updateItemInDatabaseHelper(context, writer, item, "modifyItemInDatabase");
- }
-
- /**
- * Update an item to the database in a specified container.
- */
- public static void updateItemInDatabase(Context context, final ItemInfo item) {
- ContentWriter writer = new ContentWriter(context);
- item.onAddToDatabase(writer);
- updateItemInDatabaseHelper(context, writer, item, "updateItemInDatabase");
- }
-
- /**
- * Add an item to the database in a specified container. Sets the container, screen, cellX and
- * cellY fields of the item. Also assigns an ID to the item.
- */
- public static void addItemToDatabase(Context context, final ItemInfo item, final long container,
- final long screenId, final int cellX, final int cellY) {
- item.container = container;
- item.cellX = cellX;
- item.cellY = cellY;
- // We store hotseat items in canonical form which is this orientation invariant position
- // in the hotseat
- if (context instanceof Launcher && screenId < 0 &&
- container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
- item.screenId = Launcher.getLauncher(context).getHotseat()
- .getOrderInHotseat(cellX, cellY);
- } else {
- item.screenId = screenId;
- }
-
- final ContentWriter writer = new ContentWriter(context);
- final ContentResolver cr = context.getContentResolver();
- item.onAddToDatabase(writer);
-
- item.id = LauncherSettings.Settings.call(cr, LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
- .getLong(LauncherSettings.Settings.EXTRA_VALUE);
-
- writer.put(LauncherSettings.Favorites._ID, item.id);
-
- final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
- final Context appContext = context.getApplicationContext();
- Runnable r = new Runnable() {
- public void run() {
- cr.insert(LauncherSettings.Favorites.CONTENT_URI, writer.getValues(appContext));
-
- synchronized (sBgDataModel) {
- checkItemInfoLocked(item.id, item, stackTrace);
- sBgDataModel.addItem(appContext, item, true);
- }
- }
- };
- runOnWorkerThread(r);
- }
-
- /**
- * Removes the specified item from the database
- */
- public static void deleteItemFromDatabase(Context context, final ItemInfo item) {
- ArrayList<ItemInfo> items = new ArrayList<>();
- items.add(item);
- deleteItemsFromDatabase(context, items);
- }
-
- /**
- * Removes all the items from the database matching {@param matcher}.
- */
- public static void deleteItemsFromDatabase(Context context, ItemInfoMatcher matcher) {
- deleteItemsFromDatabase(context, matcher.filterItemInfos(sBgDataModel.itemsIdMap));
- }
-
- /**
- * Removes the specified items from the database
- */
- public static void deleteItemsFromDatabase(Context context,
- final Iterable<? extends ItemInfo> items) {
- final ContentResolver cr = context.getContentResolver();
- final Context appContext = context.getApplicationContext();
- Runnable r = new Runnable() {
- public void run() {
- for (ItemInfo item : items) {
- final Uri uri = LauncherSettings.Favorites.getContentUri(item.id);
- cr.delete(uri, null, null);
-
- sBgDataModel.removeItem(appContext, item);
- }
- }
- };
- runOnWorkerThread(r);
- }
-
/**
* Update the order of the workspace screens in the database. The array list contains
* a list of screen ids in the order that they should appear.
@@ -654,27 +369,6 @@
}
/**
- * Remove the specified folder and all its contents from the database.
- */
- public static void deleteFolderAndContentsFromDatabase(Context context, final FolderInfo info) {
- final ContentResolver cr = context.getContentResolver();
- final Context appContext = context.getApplicationContext();
-
- Runnable r = new Runnable() {
- public void run() {
- cr.delete(LauncherSettings.Favorites.CONTENT_URI,
- LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
- sBgDataModel.removeItem(appContext, info.contents);
- info.contents.clear();
-
- cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
- sBgDataModel.removeItem(appContext, info);
- }
- };
- runOnWorkerThread(r);
- }
-
- /**
* Set this as the current Launcher activity object for the loader.
*/
public void initialize(Callbacks callbacks) {
@@ -2196,6 +1890,11 @@
}
});
}
+
+ public ModelWriter getModelWriter() {
+ // Updates from model task, do not deal with icon position in hotseat.
+ return mModel.getWriter(false /* hasVerticalHotseat */);
+ }
}
public void updateAndBindShortcutInfo(final ShortcutInfo si, final ShortcutInfoCompat info) {
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 6266fae..e71ef2c 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -55,6 +55,7 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.dynamicui.ExtractionUtils;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.ManagedProfileHeuristic;
@@ -91,7 +92,10 @@
}
mListenerHandler = new Handler(mListenerWrapper);
- LauncherAppState.setLauncherProvider(this);
+ // The content provider exists for the entire duration of the launcher main process and
+ // is the first component to get created. Initializing FileLog here ensures that it's
+ // always available in the main process.
+ FileLog.setDir(getContext().getApplicationContext().getFilesDir());
return true;
}
diff --git a/src/com/android/launcher3/LauncherViewPropertyAnimator.java b/src/com/android/launcher3/LauncherViewPropertyAnimator.java
deleted file mode 100644
index 4406a2c..0000000
--- a/src/com/android/launcher3/LauncherViewPropertyAnimator.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3;
-
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.TimeInterpolator;
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-
-public class LauncherViewPropertyAnimator extends Animator implements AnimatorListener {
-
- enum Properties {
- TRANSLATION_X,
- TRANSLATION_Y,
- SCALE_X,
- SCALE_Y,
- ROTATION_Y,
- ALPHA,
- START_DELAY,
- DURATION,
- INTERPOLATOR,
- WITH_LAYER
- }
- EnumSet<Properties> mPropertiesToSet = EnumSet.noneOf(Properties.class);
- ViewPropertyAnimator mViewPropertyAnimator;
- View mTarget;
-
- float mTranslationX;
- float mTranslationY;
- float mScaleX;
- float mScaleY;
- float mRotationY;
- float mAlpha;
- long mStartDelay;
- long mDuration;
- TimeInterpolator mInterpolator;
- ArrayList<Animator.AnimatorListener> mListeners = new ArrayList<>();
- boolean mRunning = false;
- FirstFrameAnimatorHelper mFirstFrameHelper;
-
- public LauncherViewPropertyAnimator(View target) {
- mTarget = target;
- }
-
- @Override
- public void addListener(Animator.AnimatorListener listener) {
- mListeners.add(listener);
- }
-
- @Override
- public void cancel() {
- if (mViewPropertyAnimator != null) {
- mViewPropertyAnimator.cancel();
- }
- }
-
- @Override
- public Animator clone() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void end() {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public long getDuration() {
- return mDuration;
- }
-
- @Override
- public ArrayList<Animator.AnimatorListener> getListeners() {
- return mListeners;
- }
-
- @Override
- public long getStartDelay() {
- return mStartDelay;
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationCancel(this);
- }
- mRunning = false;
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationEnd(this);
- }
- mRunning = false;
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationRepeat(this);
- }
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- // This is the first time we get a handle to the internal ValueAnimator
- // used by the ViewPropertyAnimator.
- mFirstFrameHelper.onAnimationStart(animation);
-
- for (int i = 0; i < mListeners.size(); i++) {
- Animator.AnimatorListener listener = mListeners.get(i);
- listener.onAnimationStart(this);
- }
- mRunning = true;
- }
-
- @Override
- public boolean isRunning() {
- return mRunning;
- }
-
- @Override
- public boolean isStarted() {
- return mViewPropertyAnimator != null;
- }
-
- @Override
- public void removeAllListeners() {
- mListeners.clear();
- }
-
- @Override
- public void removeListener(Animator.AnimatorListener listener) {
- mListeners.remove(listener);
- }
-
- @Override
- public Animator setDuration(long duration) {
- mPropertiesToSet.add(Properties.DURATION);
- mDuration = duration;
- return this;
- }
-
- @Override
- public void setInterpolator(TimeInterpolator value) {
- mPropertiesToSet.add(Properties.INTERPOLATOR);
- mInterpolator = value;
- }
-
- @Override
- public void setStartDelay(long startDelay) {
- mPropertiesToSet.add(Properties.START_DELAY);
- mStartDelay = startDelay;
- }
-
- @Override
- public void setTarget(Object target) {
- throw new RuntimeException("Not implemented");
- }
-
- @Override
- public void setupEndValues() {
-
- }
-
- @Override
- public void setupStartValues() {
- }
-
- @Override
- public void start() {
- mViewPropertyAnimator = mTarget.animate();
-
- // FirstFrameAnimatorHelper hooks itself up to the updates on the animator,
- // and then adjusts the play time to keep the first two frames jank-free
- mFirstFrameHelper = new FirstFrameAnimatorHelper(mViewPropertyAnimator, mTarget);
-
- if (mPropertiesToSet.contains(Properties.TRANSLATION_X)) {
- mViewPropertyAnimator.translationX(mTranslationX);
- }
- if (mPropertiesToSet.contains(Properties.TRANSLATION_Y)) {
- mViewPropertyAnimator.translationY(mTranslationY);
- }
- if (mPropertiesToSet.contains(Properties.SCALE_X)) {
- mViewPropertyAnimator.scaleX(mScaleX);
- }
- if (mPropertiesToSet.contains(Properties.ROTATION_Y)) {
- mViewPropertyAnimator.rotationY(mRotationY);
- }
- if (mPropertiesToSet.contains(Properties.SCALE_Y)) {
- mViewPropertyAnimator.scaleY(mScaleY);
- }
- if (mPropertiesToSet.contains(Properties.ALPHA)) {
- mViewPropertyAnimator.alpha(mAlpha);
- }
- if (mPropertiesToSet.contains(Properties.START_DELAY)) {
- mViewPropertyAnimator.setStartDelay(mStartDelay);
- }
- if (mPropertiesToSet.contains(Properties.DURATION)) {
- mViewPropertyAnimator.setDuration(mDuration);
- }
- if (mPropertiesToSet.contains(Properties.INTERPOLATOR)) {
- mViewPropertyAnimator.setInterpolator(mInterpolator);
- }
- if (mPropertiesToSet.contains(Properties.WITH_LAYER)) {
- mViewPropertyAnimator.withLayer();
- }
- mViewPropertyAnimator.setListener(this);
- mViewPropertyAnimator.start();
- LauncherAnimUtils.cancelOnDestroyActivity(this);
- }
-
- public LauncherViewPropertyAnimator translationX(float value) {
- mPropertiesToSet.add(Properties.TRANSLATION_X);
- mTranslationX = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator translationY(float value) {
- mPropertiesToSet.add(Properties.TRANSLATION_Y);
- mTranslationY = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator scaleX(float value) {
- mPropertiesToSet.add(Properties.SCALE_X);
- mScaleX = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator scaleY(float value) {
- mPropertiesToSet.add(Properties.SCALE_Y);
- mScaleY = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator rotationY(float value) {
- mPropertiesToSet.add(Properties.ROTATION_Y);
- mRotationY = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator alpha(float value) {
- mPropertiesToSet.add(Properties.ALPHA);
- mAlpha = value;
- return this;
- }
-
- public LauncherViewPropertyAnimator withLayer() {
- mPropertiesToSet.add(Properties.WITH_LAYER);
- return this;
- }
-}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 76e2073..fb6a611 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -47,6 +47,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Interpolator;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.util.LauncherEdgeEffect;
import com.android.launcher3.util.Thunk;
@@ -1998,11 +1999,12 @@
// Animate the drag view back to the original position
private void animateDragViewToOriginalPosition() {
if (mDragView != null) {
- Animator anim = new LauncherViewPropertyAnimator(mDragView)
- .translationX(0)
- .translationY(0)
- .scaleX(1)
- .scaleY(1)
+ Animator anim = LauncherAnimUtils.ofPropertyValuesHolder(mDragView,
+ new PropertyListBuilder()
+ .scale(1)
+ .translationX(0)
+ .translationY(0)
+ .build())
.setDuration(REORDERING_DROP_REPOSITION_DURATION);
anim.addListener(new AnimatorListenerAdapter() {
@Override
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index 815fd10..43fa4aa 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -35,6 +35,7 @@
import com.android.launcher3.IconCache.ItemInfoUpdateReceiver;
import com.android.launcher3.graphics.DrawableFactory;
import com.android.launcher3.model.PackageItemInfo;
+import com.android.launcher3.util.Themes;
public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
implements OnClickListener, ItemInfoUpdateReceiver {
@@ -69,7 +70,7 @@
mDisabledForSafeMode = disabledForSafeMode;
mPaint = new TextPaint();
- mPaint.setColor(Utilities.getAttrColor(getContext(), android.R.attr.textColorPrimary));
+ mPaint.setColor(Themes.getAttrColor(getContext(), android.R.attr.textColorPrimary));
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX,
mLauncher.getDeviceProfile().iconTextSizePx, getResources().getDisplayMetrics()));
setBackgroundResource(R.drawable.round_rect_primary);
diff --git a/src/com/android/launcher3/PinchAnimationManager.java b/src/com/android/launcher3/PinchAnimationManager.java
index bae246e..f8196e5 100644
--- a/src/com/android/launcher3/PinchAnimationManager.java
+++ b/src/com/android/launcher3/PinchAnimationManager.java
@@ -24,6 +24,7 @@
import android.view.View;
import android.view.animation.LinearInterpolator;
+import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
@@ -211,7 +212,8 @@
}
private void animateShowHideView(int index, final View view, boolean show) {
- Animator animator = new LauncherViewPropertyAnimator(view).alpha(show ? 1 : 0).withLayer();
+ Animator animator = ObjectAnimator.ofFloat(view, View.ALPHA, show ? 1 : 0);
+ animator.addListener(new AnimationLayerSet(view));
if (show) {
view.setVisibility(View.VISIBLE);
} else {
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 78774f3..abc5367 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -27,7 +27,6 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -608,17 +607,6 @@
return c == null || c.isEmpty();
}
- public static int getColorAccent(Context context) {
- return getAttrColor(context, android.R.attr.colorAccent);
- }
-
- public static int getAttrColor(Context context, int attr) {
- TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
- int colorAccent = ta.getColor(0, 0);
- ta.recycle();
- return colorAccent;
- }
-
public static void sendCustomAccessibilityEvent(View target, int type, String text) {
AccessibilityManager accessibilityManager = (AccessibilityManager)
target.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 3512210..689cc9b 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -14,22 +14,24 @@
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.UserHandle;
+import android.support.v4.graphics.ColorUtils;
import android.util.Log;
import android.util.LongSparseArray;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.ShortcutConfigActivityInfo;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.graphics.ShadowGenerator;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.ComponentKey;
@@ -366,30 +368,13 @@
drawable.setBounds(x, 0, x + previewWidth, previewHeight);
drawable.draw(c);
} else {
- Resources res = mContext.getResources();
- float shadowBlur = res.getDimension(R.dimen.widget_preview_shadow_blur);
- float keyShadowDistance = res.getDimension(R.dimen.widget_preview_key_shadow_distance);
- float corner = res.getDimension(R.dimen.widget_preview_corner_radius);
-
- RectF boxRect = new RectF(shadowBlur, shadowBlur,
- previewWidth - shadowBlur, previewHeight - shadowBlur - keyShadowDistance);
-
final Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
- p.setColor(0xFFFFFFFF);
-
- // Key shadow
- p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
- ShadowGenerator.KEY_SHADOW_ALPHA << 24);
- c.drawRoundRect(boxRect, corner, corner, p);
-
- // Ambient shadow
- p.setShadowLayer(shadowBlur, 0, 0, ShadowGenerator.AMBIENT_SHADOW_ALPHA << 24);
- c.drawRoundRect(boxRect, corner, corner, p);
+ RectF boxRect = drawBoxWithShadow(c, p, previewWidth, previewHeight);
// Draw horizontal and vertical lines to represent individual columns.
- p.clearShadowLayer();
p.setStyle(Paint.Style.STROKE);
- p.setStrokeWidth(res.getDimension(R.dimen.widget_preview_cell_divider_width));
+ p.setStrokeWidth(mContext.getResources()
+ .getDimension(R.dimen.widget_preview_cell_divider_width));
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
float t = boxRect.left;
@@ -426,47 +411,63 @@
return preview;
}
+ private RectF drawBoxWithShadow(Canvas c, Paint p, int width, int height) {
+ Resources res = mContext.getResources();
+ float shadowBlur = res.getDimension(R.dimen.widget_preview_shadow_blur);
+ float keyShadowDistance = res.getDimension(R.dimen.widget_preview_key_shadow_distance);
+ float corner = res.getDimension(R.dimen.widget_preview_corner_radius);
+
+ RectF bounds = new RectF(shadowBlur, shadowBlur,
+ width - shadowBlur, height - shadowBlur - keyShadowDistance);
+ p.setColor(Color.WHITE);
+
+ // Key shadow
+ p.setShadowLayer(shadowBlur, 0, keyShadowDistance,
+ ShadowGenerator.KEY_SHADOW_ALPHA << 24);
+ c.drawRoundRect(bounds, corner, corner, p);
+
+ // Ambient shadow
+ p.setShadowLayer(shadowBlur, 0, 0,
+ ColorUtils.setAlphaComponent(Color.BLACK, ShadowGenerator.AMBIENT_SHADOW_ALPHA));
+ c.drawRoundRect(bounds, corner, corner, p);
+
+ p.clearShadowLayer();
+ return bounds;
+ }
+
private Bitmap generateShortcutPreview(BaseActivity launcher, ShortcutConfigActivityInfo info,
int maxWidth, int maxHeight, Bitmap preview) {
+ int iconSize = launcher.getDeviceProfile().iconSizePx;
+ int padding = launcher.getResources()
+ .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
+
+ int size = iconSize + 2 * padding;
+ if (maxHeight < size || maxWidth < size) {
+ throw new RuntimeException("Max size is too small for preview");
+ }
final Canvas c = new Canvas();
- if (preview == null) {
- preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888);
+ if (preview == null || preview.getWidth() < size || preview.getHeight() < size) {
+ preview = Bitmap.createBitmap(size, size, Config.ARGB_8888);
c.setBitmap(preview);
- } else if (preview.getWidth() != maxWidth || preview.getHeight() != maxHeight) {
- throw new RuntimeException("Improperly sized bitmap passed as argument");
} else {
+ if (preview.getWidth() > size || preview.getHeight() > size) {
+ preview.reconfigure(size, size, preview.getConfig());
+ }
+
// Reusing bitmap. Clear it.
c.setBitmap(preview);
c.drawColor(0, PorterDuff.Mode.CLEAR);
}
+ Paint p = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ RectF boxRect = drawBoxWithShadow(c, p, size, size);
- Drawable icon = mutateOnMainThread(info.getFullResIcon(mIconCache));
- icon.setFilterBitmap(true);
+ Bitmap icon = LauncherIcons.createScaledBitmapWithoutShadow(
+ mutateOnMainThread(info.getFullResIcon(mIconCache)), mContext);
+ Rect src = new Rect(0, 0, icon.getWidth(), icon.getHeight());
- // Draw a desaturated/scaled version of the icon in the background as a watermark
- ColorMatrix colorMatrix = new ColorMatrix();
- colorMatrix.setSaturation(0);
- icon.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
- icon.setAlpha((int) (255 * 0.06f));
-
- Resources res = mContext.getResources();
- int paddingTop = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
- int paddingLeft = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_left);
- int paddingRight = res.getDimensionPixelOffset(R.dimen.shortcut_preview_padding_right);
- int scaledIconWidth = (maxWidth - paddingLeft - paddingRight);
- icon.setBounds(paddingLeft, paddingTop,
- paddingLeft + scaledIconWidth, paddingTop + scaledIconWidth);
- icon.draw(c);
-
- // Draw the final icon at top left corner.
- // TODO: use top right for RTL
- int appIconSize = launcher.getDeviceProfile().iconSizePx;
-
- icon.setAlpha(255);
- icon.setColorFilter(null);
- icon.setBounds(0, 0, appIconSize, appIconSize);
- icon.draw(c);
-
+ boxRect.set(0, 0, iconSize, iconSize);
+ boxRect.offset(padding, padding);
+ c.drawBitmap(icon, src, boxRect, p);
c.setBitmap(null);
return preview;
}
@@ -664,7 +665,6 @@
private static final class WidgetCacheKey extends ComponentKey {
- // TODO: remove dependency on size
@Thunk final String size;
public WidgetCacheKey(ComponentName componentName, UserHandle user, String size) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 3aa8825..56aa69e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2654,8 +2654,8 @@
}
}
- LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, lp.cellX,
- lp.cellY, item.spanX, item.spanY);
+ mLauncher.getModelWriter().modifyItemInDatabase(info, container, screenId,
+ lp.cellX, lp.cellY, item.spanX, item.spanY);
} else {
if (!returnToOriginalCellToPreventShuffling) {
onNoCellFound(dropTargetLayout);
@@ -3387,7 +3387,7 @@
}
// Add the item to DB before adding to screen ensures that the container and other
// values of the info is properly updated.
- LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screenId,
+ mLauncher.getModelWriter().addOrMoveItemInDatabase(info, container, screenId,
mTargetCell[0], mTargetCell[1]);
addInScreen(view, container, screenId, mTargetCell[0], mTargetCell[1],
@@ -4025,7 +4025,7 @@
HashSet<String> packages = new HashSet<>(1);
packages.add(packageName);
ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(packages, user);
- LauncherModel.deleteItemsFromDatabase(mLauncher, matcher);
+ mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
removeItemsByMatcher(matcher);
}
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 6a71bef..482a2c9 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -31,6 +31,7 @@
import android.view.animation.DecelerateInterpolator;
import com.android.launcher3.anim.AnimationLayerSet;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.util.Thunk;
@@ -337,10 +338,9 @@
if (animated) {
float oldBackgroundAlpha = cl.getBackgroundAlpha();
if (initialAlpha != finalAlpha) {
- LauncherViewPropertyAnimator alphaAnim =
- new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
- alphaAnim.alpha(finalAlpha)
- .setDuration(duration)
+ Animator alphaAnim = ObjectAnimator.ofFloat(
+ cl.getShortcutsAndWidgets(), View.ALPHA, finalAlpha);
+ alphaAnim.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
mStateAnimator.play(alphaAnim);
}
@@ -377,17 +377,16 @@
.animateAlphaAtIndex(finalQsbAlpha, Workspace.QSB_ALPHA_INDEX_STATE_CHANGE);
if (animated) {
- LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(mWorkspace);
- scale.scaleX(mNewScale)
- .scaleY(mNewScale)
- .translationY(finalWorkspaceTranslationY)
- .setDuration(duration)
- .setInterpolator(mZoomInInterpolator);
+ Animator scale = LauncherAnimUtils.ofPropertyValuesHolder(mWorkspace,
+ new PropertyListBuilder().scale(mNewScale)
+ .translationY(finalWorkspaceTranslationY).build())
+ .setDuration(duration);
+ scale.setInterpolator(mZoomInInterpolator);
mStateAnimator.play(scale);
Animator hotseatAlpha = mWorkspace.createHotseatAlphaAnimator(finalHotseatAlpha);
- LauncherViewPropertyAnimator overviewPanelAlpha =
- new LauncherViewPropertyAnimator(overviewPanel).alpha(finalOverviewPanelAlpha);
+ Animator overviewPanelAlpha = ObjectAnimator.ofFloat(
+ overviewPanel, View.ALPHA, finalOverviewPanelAlpha);
overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel,
accessibilityEnabled));
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index b77493b..a476650 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -168,7 +168,7 @@
public void run() {
if (item instanceof AppInfo) {
ShortcutInfo info = ((AppInfo) item).makeShortcut();
- LauncherModel.addItemToDatabase(mLauncher, info,
+ mLauncher.getModelWriter().addItemToDatabase(info,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
@@ -194,7 +194,7 @@
final int[] coordinates = new int[2];
final long screenId = findSpaceOnWorkspace(item, coordinates);
- LauncherModel.moveItemInDatabase(mLauncher, info,
+ mLauncher.getModelWriter().moveItemInDatabase(info,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
@@ -304,7 +304,7 @@
((LauncherAppWidgetHostView) host).updateAppWidgetSize(null,
sizeRange.left, sizeRange.top, sizeRange.right, sizeRange.bottom);
host.requestLayout();
- LauncherModel.updateItemInDatabase(mLauncher, info);
+ mLauncher.getModelWriter().updateItemInDatabase(info);
announceConfirmation(mLauncher.getString(R.string.widget_resized, info.spanX, info.spanY));
}
diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
index f7ca703..b784fe7 100644
--- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
@@ -59,7 +59,7 @@
Runnable onComplete = new Runnable() {
@Override
public void run() {
- LauncherModel.addItemToDatabase(mLauncher, info,
+ mLauncher.getModelWriter().addItemToDatabase(info,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
ArrayList<ItemInfo> itemList = new ArrayList<>();
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 54d0bbe..0732004 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -464,10 +464,6 @@
setLayoutParams(mlp);
} else {
View navBarBg = findViewById(R.id.nav_bar_bg);
- if (Utilities.isAtLeastO()) {
- navBarBg.setBackgroundColor(getResources().getColor(
- R.color.all_apps_light_navbar_color));
- }
ViewGroup.LayoutParams navBarBgLp = navBarBg.getLayoutParams();
navBarBgLp.height = insets.bottom;
navBarBg.setLayoutParams(navBarBgLp);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 547ab2b..b436fa2 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -7,7 +7,6 @@
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.graphics.Color;
-import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.Log;
@@ -26,6 +25,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TouchController;
/**
@@ -102,7 +102,7 @@
mProgress = 1f;
mEvaluator = new ArgbEvaluator();
- mAllAppsBackgroundColor = ContextCompat.getColor(l, R.color.all_apps_container_color);
+ mAllAppsBackgroundColor = Themes.getAttrColor(l, android.R.attr.colorPrimary);
}
@Override
diff --git a/src/com/android/launcher3/anim/AnimationLayerSet.java b/src/com/android/launcher3/anim/AnimationLayerSet.java
index d2f5e78..14bcd17 100644
--- a/src/com/android/launcher3/anim/AnimationLayerSet.java
+++ b/src/com/android/launcher3/anim/AnimationLayerSet.java
@@ -29,7 +29,16 @@
*/
public class AnimationLayerSet extends AnimatorListenerAdapter {
- private final HashMap<View, Integer> mViewsToLayerTypeMap = new HashMap<>();
+ private final HashMap<View, Integer> mViewsToLayerTypeMap;
+
+ public AnimationLayerSet() {
+ mViewsToLayerTypeMap = new HashMap<>();
+ }
+
+ public AnimationLayerSet(View v) {
+ mViewsToLayerTypeMap = new HashMap<>(1);
+ addView(v);
+ }
public void addView(View v) {
mViewsToLayerTypeMap.put(v, v.getLayerType());
diff --git a/src/com/android/launcher3/anim/PropertyListBuilder.java b/src/com/android/launcher3/anim/PropertyListBuilder.java
new file mode 100644
index 0000000..33e7f66
--- /dev/null
+++ b/src/com/android/launcher3/anim/PropertyListBuilder.java
@@ -0,0 +1,50 @@
+package com.android.launcher3.anim;
+
+import android.animation.PropertyValuesHolder;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * Helper class to build a list of {@link PropertyValuesHolder} for view properties
+ */
+public class PropertyListBuilder {
+
+ private final ArrayList<PropertyValuesHolder> mProperties = new ArrayList<>();
+
+ public PropertyListBuilder translationX(float value) {
+ mProperties.add(PropertyValuesHolder.ofFloat(View.TRANSLATION_X, value));
+ return this;
+ }
+
+ public PropertyListBuilder translationY(float value) {
+ mProperties.add(PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, value));
+ return this;
+ }
+
+ public PropertyListBuilder scaleX(float value) {
+ mProperties.add(PropertyValuesHolder.ofFloat(View.SCALE_X, value));
+ return this;
+ }
+
+ public PropertyListBuilder scaleY(float value) {
+ mProperties.add(PropertyValuesHolder.ofFloat(View.SCALE_Y, value));
+ return this;
+ }
+
+ /**
+ * Helper method to set both scaleX and scaleY
+ */
+ public PropertyListBuilder scale(float value) {
+ return scaleX(value).scaleY(value);
+ }
+
+ public PropertyListBuilder alpha(float value) {
+ mProperties.add(PropertyValuesHolder.ofFloat(View.ALPHA, value));
+ return this;
+ }
+
+ public PropertyValuesHolder[] build() {
+ return mProperties.toArray(new PropertyValuesHolder[mProperties.size()]);
+ }
+}
diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java
index 1a127dc..f94d442 100644
--- a/src/com/android/launcher3/dynamicui/ColorExtractionService.java
+++ b/src/com/android/launcher3/dynamicui/ColorExtractionService.java
@@ -98,7 +98,7 @@
if (bitmap != null) {
return Palette.from(bitmap).clearFilters().generate();
}
- } catch (IOException e) {
+ } catch (IOException | NullPointerException e) {
Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
}
}
@@ -129,7 +129,7 @@
if (bitmap != null) {
return Palette.from(bitmap).clearFilters().generate();
}
- } catch (IOException e) {
+ } catch (IOException | NullPointerException e) {
Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
}
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index eacea4a..4ad13d0 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -355,7 +355,7 @@
// gets saved.
String newTitle = mFolderName.getText().toString();
mInfo.setTitle(newTitle);
- LauncherModel.updateItemInDatabase(mLauncher, mInfo);
+ mLauncher.getModelWriter().updateItemInDatabase(mInfo);
Utilities.sendCustomAccessibilityEvent(
this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
@@ -445,7 +445,7 @@
// TODO: Remove this, as with multi-page folders, there will never be any overflow
for (ShortcutInfo item: overflow) {
mInfo.remove(item, false);
- LauncherModel.deleteItemFromDatabase(mLauncher, item);
+ mLauncher.getModelWriter().deleteItemFromDatabase(item);
}
DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
@@ -535,7 +535,6 @@
}
mIsOpen = true;
- mFolderIcon.growAndFadeOut();
mContent.completePendingPageChanges();
if (!mDragInProgress) {
@@ -552,6 +551,8 @@
prepareReveal();
centerAboutIcon();
+ mFolderIcon.growAndFadeOut();
+
AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth();
int height = getFolderHeight();
@@ -647,7 +648,8 @@
mPageIndicator.playEntryAnimation();
if (updateAnimationFlag) {
- mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher);
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true,
+ mLauncher.getModelWriter());
}
}
});
@@ -973,7 +975,8 @@
// been refreshed yet.
if (getItemCount() <= mContent.itemsPerPage()) {
// Show the animation, next time something is added to the folder.
- mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, false, mLauncher);
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, false,
+ mLauncher.getModelWriter());
}
if (!isFlingToDelete) {
@@ -1022,7 +1025,7 @@
items.add(info);
}
- LauncherModel.moveItemsInDatabase(mLauncher, items, mInfo.id, 0);
+ mLauncher.getModelWriter().moveItemsInDatabase(items, mInfo.id, 0);
}
public void notifyDrop() {
@@ -1086,6 +1089,7 @@
int folderPivotY = height / 2 + (centeredTop - top);
setPivotX(folderPivotX);
setPivotY(folderPivotY);
+
mFolderIconPivotX = (int) (mFolderIcon.getMeasuredWidth() *
(1.0f * folderPivotX / width));
mFolderIconPivotY = (int) (mFolderIcon.getMeasuredHeight() *
@@ -1189,8 +1193,8 @@
mInfo.screenId);
ShortcutInfo finalItem = mInfo.contents.remove(0);
newIcon = mLauncher.createShortcut(cellLayout, finalItem);
- LauncherModel.addOrMoveItemInDatabase(mLauncher, finalItem, mInfo.container,
- mInfo.screenId, mInfo.cellX, mInfo.cellY);
+ mLauncher.getModelWriter().addOrMoveItemInDatabase(finalItem,
+ mInfo.container, mInfo.screenId, mInfo.cellX, mInfo.cellY);
}
// Remove the folder
@@ -1301,8 +1305,8 @@
currentDragView = mContent.createAndAddViewForRank(si, mEmptyCellRank);
// Actually move the item in the database if it was an external drag. Call this
// before creating the view, so that ShortcutInfo is updated appropriately.
- LauncherModel.addOrMoveItemInDatabase(
- mLauncher, si, mInfo.id, 0, si.cellX, si.cellY);
+ mLauncher.getModelWriter().addOrMoveItemInDatabase(
+ si, mInfo.id, 0, si.cellX, si.cellY);
// We only need to update the locations if it doesn't get handled in #onDropCompleted.
if (d.dragSource != this) {
@@ -1342,7 +1346,7 @@
if (mContent.getPageCount() > 1) {
// The animation has already been shown while opening the folder.
- mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher);
+ mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher.getModelWriter());
}
if (d.stateAnnouncer != null) {
@@ -1366,8 +1370,8 @@
public void onAdd(ShortcutInfo item) {
mContent.createAndAddViewForRank(item, mContent.allocateRankForNewItem());
mItemsInvalidated = true;
- LauncherModel.addOrMoveItemInDatabase(
- mLauncher, item, mInfo.id, 0, item.cellX, item.cellY);
+ mLauncher.getModelWriter().addOrMoveItemInDatabase(
+ item, mInfo.id, 0, item.cellX, item.cellY);
}
public void onRemove(ShortcutInfo item) {
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 4a2a735..eecce18 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -45,6 +45,7 @@
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
import com.android.launcher3.pageindicators.PageIndicator;
+import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import java.util.ArrayList;
@@ -107,7 +108,7 @@
mIsRtl = Utilities.isRtl(getResources());
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- setEdgeGlowColor(getResources().getColor(R.color.folder_edge_effect_color));
+ setEdgeGlowColor(Themes.getAttrColor(context, android.R.attr.colorEdgeEffect));
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
}
@@ -336,7 +337,7 @@
info.cellY = newY;
info.rank = rank;
if (saveChanges) {
- LauncherModel.addOrMoveItemInDatabase(getContext(), info,
+ mFolder.mLauncher.getModelWriter().addOrMoveItemInDatabase(info,
mFolder.mInfo.id, 0, info.cellX, info.cellY);
}
}
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 2493447..8b207bb 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -77,7 +77,7 @@
if (mPreloadProgressPath == null) {
mPreloadProgressPath = getPreloadProgressPath(context);
}
- return new PreloadIconDrawable(icon, mPreloadProgressPath);
+ return new PreloadIconDrawable(icon, mPreloadProgressPath, context);
}
diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java
index 7cb69b3..23c6a12 100644
--- a/src/com/android/launcher3/graphics/IconPalette.java
+++ b/src/com/android/launcher3/graphics/IconPalette.java
@@ -23,6 +23,8 @@
import android.util.Log;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Themes;
/**
* Contains colors based on the dominant color of an icon.
@@ -36,7 +38,6 @@
private static final float MIN_PRELOAD_COLOR_SATURATION = 0.2f;
private static final float MIN_PRELOAD_COLOR_LIGHTNESS = 0.6f;
- private static final int DEFAULT_PRELOAD_COLOR = 0xFF009688;
public final int dominantColor;
public final int backgroundColor;
@@ -53,14 +54,14 @@
/**
* Returns a color suitable for the progress bar color of preload icon.
*/
- public int getPreloadProgressColor() {
+ public int getPreloadProgressColor(Context context) {
int result = dominantColor;
// Make sure that the dominant color has enough saturation to be visible properly.
float[] hsv = new float[3];
Color.colorToHSV(result, hsv);
if (hsv[1] < MIN_PRELOAD_COLOR_SATURATION) {
- result = DEFAULT_PRELOAD_COLOR;
+ result = Themes.getColorAccent(context);
} else {
hsv[2] = Math.max(MIN_PRELOAD_COLOR_LIGHTNESS, hsv[2]);
result = Color.HSVToColor(hsv);
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 3fffb5b..1a50dfe 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -228,7 +228,7 @@
* create MaskableIconDrawable.
*/
static Drawable wrapToMaskableIconDrawable(Context context, Drawable drawable) {
- if (!(ProviderConfig.IS_DOGFOOD_BUILD && Utilities.isAtLeastO())) {
+ if (!(FeatureFlags.LEGACY_ICON_TREATMENT && Utilities.isAtLeastO())) {
return drawable;
}
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index bc07ce1..3514a37 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -20,6 +20,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
+import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
@@ -75,6 +76,8 @@
private final Matrix mTmpMatrix = new Matrix();
private final PathMeasure mPathMeasure = new PathMeasure();
+ private final Context mContext;
+
// Path in [0, 100] bounds.
private final Path mProgressPath;
@@ -100,8 +103,9 @@
/**
* @param progressPath fixed path in the bounds [0, 0, 100, 100] representing a progress bar.
*/
- public PreloadIconDrawable(Bitmap b, Path progressPath) {
+ public PreloadIconDrawable(Bitmap b, Path progressPath, Context context) {
super(b);
+ mContext = context;
mProgressPath = progressPath;
mScaledTrackPath = new Path();
mScaledProgressPath = new Path();
@@ -262,7 +266,7 @@
setIsDisabled(true);
} else if (mIndicatorColor == 0) {
// Update the indicator color
- mIndicatorColor = getIconPalette().getPreloadProgressColor();
+ mIndicatorColor = getIconPalette().getPreloadProgressColor(mContext);
}
if (progress < 1 && progress > 0) {
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index c97b3b5..9696054 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -95,7 +95,9 @@
}
// Add the shortcut to the db
- addItemToDatabase(context, itemInfo, screenId, cordinates);
+ getModelWriter().addItemToDatabase(itemInfo,
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId,
+ cordinates[0], cordinates[1]);
// Save the ShortcutInfo for binding in the workspace
addedItemsFinal.add(itemInfo);
@@ -129,11 +131,6 @@
}
}
- protected void addItemToDatabase(Context context, ItemInfo item, long screenId, int[] pos) {
- LauncherModel.addItemToDatabase(context, item,
- LauncherSettings.Favorites.CONTAINER_DESKTOP, screenId, pos[0], pos[1]);
- }
-
protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) {
LauncherModel.updateWorkspaceScreenOrder(context, workspaceScreens);
}
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index bbc7ae4..e50b912 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -27,6 +27,7 @@
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.logging.FileLog;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.LongArrayMap;
@@ -889,6 +890,23 @@
.apply();
}
+ public static void logDeviceProfileIfChanged(InvariantDeviceProfile idp, Context context) {
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ String gridSizeString = getPointString(idp.numColumns, idp.numRows);
+
+ int oldHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons);
+ String oldSize = prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, gridSizeString);
+ if (gridSizeString.equals(oldSize) && idp.numHotseatIcons == oldHotseatCount) {
+ // Skip if workspace and hotseat sizes have not changed.
+ return;
+ }
+
+ FileLog.e(TAG, "Grid size changed" + gridSizeString);
+ FileLog.e(TAG, " oldSize: " + oldSize + " , hotseat: " + oldHotseatCount);
+ FileLog.e(TAG, " newSize: " + gridSizeString + " , hotseat: " + idp.numHotseatIcons);
+ idp.dumpDisplayInfo(context);
+ }
+
/**
* Migrates the workspace and hotseat in case their sizes changed.
* @return false if the migration failed.
@@ -900,7 +918,7 @@
String gridSizeString = getPointString(idp.numColumns, idp.numRows);
if (gridSizeString.equals(prefs.getString(KEY_MIGRATION_SRC_WORKSPACE_SIZE, "")) &&
- idp.numHotseatIcons != prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons)) {
+ idp.numHotseatIcons == prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons)) {
// Skip if workspace and hotseat sizes have not changed.
return true;
}
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
new file mode 100644
index 0000000..4931dca
--- /dev/null
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.util.Log;
+
+import com.android.launcher3.FolderInfo;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.LauncherSettings.Settings;
+import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.LooperExecuter;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.Executor;
+
+/**
+ * Class for handling model updates.
+ */
+public class ModelWriter {
+
+ private static final String TAG = "ModelWriter";
+
+ private final Context mContext;
+ private final BgDataModel mBgDataModel;
+ private final Executor mWorkerExecutor;
+ private final boolean mHasVerticalHotseat;
+
+ public ModelWriter(Context context, BgDataModel dataModel, boolean hasVerticalHotseat) {
+ mContext = context;
+ mBgDataModel = dataModel;
+ mWorkerExecutor = new LooperExecuter(LauncherModel.getWorkerLooper());
+ mHasVerticalHotseat = hasVerticalHotseat;
+ }
+
+ private void updateItemInfoProps(
+ ItemInfo item, long container, long screenId, int cellX, int cellY) {
+ item.container = container;
+ item.cellX = cellX;
+ item.cellY = cellY;
+ // We store hotseat items in canonical form which is this orientation invariant position
+ // in the hotseat
+ if (container == Favorites.CONTAINER_HOTSEAT) {
+ item.screenId = mHasVerticalHotseat
+ ? LauncherAppState.getIDP(mContext).numHotseatIcons - cellY - 1 : cellX;
+ } else {
+ item.screenId = screenId;
+ }
+ }
+
+ /**
+ * Adds an item to the DB if it was not created previously, or move it to a new
+ * <container, screen, cellX, cellY>
+ */
+ public void addOrMoveItemInDatabase(ItemInfo item,
+ long container, long screenId, int cellX, int cellY) {
+ if (item.container == ItemInfo.NO_ID) {
+ // From all apps
+ addItemToDatabase(item, container, screenId, cellX, cellY);
+ } else {
+ // From somewhere else
+ moveItemInDatabase(item, container, screenId, cellX, cellY);
+ }
+ }
+
+ private void checkItemInfoLocked(long itemId, ItemInfo item, StackTraceElement[] stackTrace) {
+ ItemInfo modelItem = mBgDataModel.itemsIdMap.get(itemId);
+ if (modelItem != null && item != modelItem) {
+ // check all the data is consistent
+ if (modelItem instanceof ShortcutInfo && item instanceof ShortcutInfo) {
+ ShortcutInfo modelShortcut = (ShortcutInfo) modelItem;
+ ShortcutInfo shortcut = (ShortcutInfo) item;
+ if (modelShortcut.title.toString().equals(shortcut.title.toString()) &&
+ modelShortcut.intent.filterEquals(shortcut.intent) &&
+ modelShortcut.id == shortcut.id &&
+ modelShortcut.itemType == shortcut.itemType &&
+ modelShortcut.container == shortcut.container &&
+ modelShortcut.screenId == shortcut.screenId &&
+ modelShortcut.cellX == shortcut.cellX &&
+ modelShortcut.cellY == shortcut.cellY &&
+ modelShortcut.spanX == shortcut.spanX &&
+ modelShortcut.spanY == shortcut.spanY) {
+ // For all intents and purposes, this is the same object
+ return;
+ }
+ }
+
+ // the modelItem needs to match up perfectly with item if our model is
+ // to be consistent with the database-- for now, just require
+ // modelItem == item or the equality check above
+ String msg = "item: " + ((item != null) ? item.toString() : "null") +
+ "modelItem: " +
+ ((modelItem != null) ? modelItem.toString() : "null") +
+ "Error: ItemInfo passed to checkItemInfo doesn't match original";
+ RuntimeException e = new RuntimeException(msg);
+ if (stackTrace != null) {
+ e.setStackTrace(stackTrace);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Move an item in the DB to a new <container, screen, cellX, cellY>
+ */
+ public void moveItemInDatabase(final ItemInfo item,
+ long container, long screenId, int cellX, int cellY) {
+ updateItemInfoProps(item, container, screenId, cellX, cellY);
+
+ final ContentWriter writer = new ContentWriter(mContext)
+ .put(Favorites.CONTAINER, item.container)
+ .put(Favorites.CELLX, item.cellX)
+ .put(Favorites.CELLY, item.cellY)
+ .put(Favorites.RANK, item.rank)
+ .put(Favorites.SCREEN, item.screenId);
+
+ mWorkerExecutor.execute(new UpdateItemRunnable(item, writer));
+ }
+
+ /**
+ * Move items in the DB to a new <container, screen, cellX, cellY>. We assume that the
+ * cellX, cellY have already been updated on the ItemInfos.
+ */
+ public void moveItemsInDatabase(final ArrayList<ItemInfo> items, long container, int screen) {
+ ArrayList<ContentValues> contentValues = new ArrayList<>();
+ int count = items.size();
+
+ for (int i = 0; i < count; i++) {
+ ItemInfo item = items.get(i);
+ updateItemInfoProps(item, container, screen, item.cellX, item.cellY);
+
+ final ContentValues values = new ContentValues();
+ values.put(Favorites.CONTAINER, item.container);
+ values.put(Favorites.CELLX, item.cellX);
+ values.put(Favorites.CELLY, item.cellY);
+ values.put(Favorites.RANK, item.rank);
+ values.put(Favorites.SCREEN, item.screenId);
+
+ contentValues.add(values);
+ }
+ mWorkerExecutor.execute(new UpdateItemsRunnable(items, contentValues));
+ }
+
+ /**
+ * Move and/or resize item in the DB to a new <container, screen, cellX, cellY, spanX, spanY>
+ */
+ public void modifyItemInDatabase(final ItemInfo item,
+ long container, long screenId, int cellX, int cellY, int spanX, int spanY) {
+ updateItemInfoProps(item, container, screenId, cellX, cellY);
+ item.spanX = spanX;
+ item.spanY = spanY;
+
+ final ContentWriter writer = new ContentWriter(mContext)
+ .put(Favorites.CONTAINER, item.container)
+ .put(Favorites.CELLX, item.cellX)
+ .put(Favorites.CELLY, item.cellY)
+ .put(Favorites.RANK, item.rank)
+ .put(Favorites.SPANX, item.spanX)
+ .put(Favorites.SPANY, item.spanY)
+ .put(Favorites.SCREEN, item.screenId);
+
+ mWorkerExecutor.execute(new UpdateItemRunnable(item, writer));
+ }
+
+ /**
+ * Update an item to the database in a specified container.
+ */
+ public void updateItemInDatabase(ItemInfo item) {
+ ContentWriter writer = new ContentWriter(mContext);
+ item.onAddToDatabase(writer);
+ mWorkerExecutor.execute(new UpdateItemRunnable(item, writer));
+ }
+
+ /**
+ * Add an item to the database in a specified container. Sets the container, screen, cellX and
+ * cellY fields of the item. Also assigns an ID to the item.
+ */
+ public void addItemToDatabase(final ItemInfo item,
+ long container, long screenId, int cellX, int cellY) {
+ updateItemInfoProps(item, container, screenId, cellX, cellY);
+
+ final ContentWriter writer = new ContentWriter(mContext);
+ final ContentResolver cr = mContext.getContentResolver();
+ item.onAddToDatabase(writer);
+
+ item.id = Settings.call(cr, Settings.METHOD_NEW_ITEM_ID).getLong(Settings.EXTRA_VALUE);
+ writer.put(Favorites._ID, item.id);
+
+ final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
+ mWorkerExecutor.execute(new Runnable() {
+ public void run() {
+ cr.insert(Favorites.CONTENT_URI, writer.getValues(mContext));
+
+ synchronized (mBgDataModel) {
+ checkItemInfoLocked(item.id, item, stackTrace);
+ mBgDataModel.addItem(mContext, item, true);
+ }
+ }
+ });
+ }
+
+ /**
+ * Removes the specified item from the database
+ */
+ public void deleteItemFromDatabase(ItemInfo item) {
+ deleteItemsFromDatabase(Arrays.asList(item));
+ }
+
+ /**
+ * Removes all the items from the database matching {@param matcher}.
+ */
+ public void deleteItemsFromDatabase(ItemInfoMatcher matcher) {
+ deleteItemsFromDatabase(matcher.filterItemInfos(mBgDataModel.itemsIdMap));
+ }
+
+ /**
+ * Removes the specified items from the database
+ */
+ public void deleteItemsFromDatabase(final Iterable<? extends ItemInfo> items) {
+ mWorkerExecutor.execute(new Runnable() {
+ public void run() {
+ for (ItemInfo item : items) {
+ final Uri uri = Favorites.getContentUri(item.id);
+ mContext.getContentResolver().delete(uri, null, null);
+
+ mBgDataModel.removeItem(mContext, item);
+ }
+ }
+ });
+ }
+
+ /**
+ * Remove the specified folder and all its contents from the database.
+ */
+ public void deleteFolderAndContentsFromDatabase(final FolderInfo info) {
+ mWorkerExecutor.execute(new Runnable() {
+ public void run() {
+ ContentResolver cr = mContext.getContentResolver();
+ cr.delete(LauncherSettings.Favorites.CONTENT_URI,
+ LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+ mBgDataModel.removeItem(mContext, info.contents);
+ info.contents.clear();
+
+ cr.delete(LauncherSettings.Favorites.getContentUri(info.id), null, null);
+ mBgDataModel.removeItem(mContext, info);
+ }
+ });
+ }
+
+ private class UpdateItemRunnable extends UpdateItemBaseRunnable {
+ private final ItemInfo mItem;
+ private final ContentWriter mWriter;
+ private final long mItemId;
+
+ UpdateItemRunnable(ItemInfo item, ContentWriter writer) {
+ mItem = item;
+ mWriter = writer;
+ mItemId = item.id;
+ }
+
+ @Override
+ public void run() {
+ Uri uri = Favorites.getContentUri(mItemId);
+ mContext.getContentResolver().update(uri, mWriter.getValues(mContext), null, null);
+ updateItemArrays(mItem, mItemId);
+ }
+ }
+
+ private class UpdateItemsRunnable extends UpdateItemBaseRunnable {
+ private final ArrayList<ContentValues> mValues;
+ private final ArrayList<ItemInfo> mItems;
+
+ UpdateItemsRunnable(ArrayList<ItemInfo> items, ArrayList<ContentValues> values) {
+ mValues = values;
+ mItems = items;
+ }
+
+ @Override
+ public void run() {
+ ArrayList<ContentProviderOperation> ops = new ArrayList<>();
+ int count = mItems.size();
+ for (int i = 0; i < count; i++) {
+ ItemInfo item = mItems.get(i);
+ final long itemId = item.id;
+ final Uri uri = Favorites.getContentUri(itemId);
+ ContentValues values = mValues.get(i);
+
+ ops.add(ContentProviderOperation.newUpdate(uri).withValues(values).build());
+ updateItemArrays(item, itemId);
+ }
+ try {
+ mContext.getContentResolver().applyBatch(LauncherProvider.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private abstract class UpdateItemBaseRunnable implements Runnable {
+ private final StackTraceElement[] mStackTrace;
+
+ UpdateItemBaseRunnable() {
+ mStackTrace = new Throwable().getStackTrace();
+ }
+
+ protected void updateItemArrays(ItemInfo item, long itemId) {
+ // Lock on mBgLock *after* the db operation
+ synchronized (mBgDataModel) {
+ checkItemInfoLocked(itemId, item, mStackTrace);
+
+ if (item.container != Favorites.CONTAINER_DESKTOP &&
+ item.container != Favorites.CONTAINER_HOTSEAT) {
+ // Item is in a folder, make sure this folder exists
+ if (!mBgDataModel.folders.containsKey(item.container)) {
+ // An items container is being set to a that of an item which is not in
+ // the list of Folders.
+ String msg = "item: " + item + " container being set to: " +
+ item.container + ", not in the list of folders";
+ Log.e(TAG, msg);
+ }
+ }
+
+ // Items are added/removed from the corresponding FolderInfo elsewhere, such
+ // as in Workspace.onDrop. Here, we just add/remove them from the list of items
+ // that are on the desktop, as appropriate
+ ItemInfo modelItem = mBgDataModel.itemsIdMap.get(itemId);
+ if (modelItem != null &&
+ (modelItem.container == Favorites.CONTAINER_DESKTOP ||
+ modelItem.container == Favorites.CONTAINER_HOTSEAT)) {
+ switch (modelItem.itemType) {
+ case Favorites.ITEM_TYPE_APPLICATION:
+ case Favorites.ITEM_TYPE_SHORTCUT:
+ case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ case Favorites.ITEM_TYPE_FOLDER:
+ if (!mBgDataModel.workspaceItems.contains(modelItem)) {
+ mBgDataModel.workspaceItems.add(modelItem);
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ mBgDataModel.workspaceItems.remove(modelItem);
+ }
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 211b979..ee7186a 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -270,7 +270,7 @@
updatedShortcuts.add(si);
}
if (infoUpdated) {
- LauncherModel.updateItemInDatabase(context, si);
+ getModelWriter().updateItemInDatabase(si);
}
} else if (info instanceof LauncherAppWidgetInfo && mOp == OP_ADD) {
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
@@ -287,7 +287,7 @@
widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
widgets.add(widgetInfo);
- LauncherModel.updateItemInDatabase(context, widgetInfo);
+ getModelWriter().updateItemInDatabase(widgetInfo);
}
}
}
@@ -295,7 +295,7 @@
bindUpdatedShortcuts(updatedShortcuts, removedShortcuts, mUser);
if (!removedShortcuts.isEmpty()) {
- LauncherModel.deleteItemsFromDatabase(context, removedShortcuts);
+ getModelWriter().deleteItemsFromDatabase(removedShortcuts);
}
if (!widgets.isEmpty()) {
@@ -332,10 +332,10 @@
}
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
- LauncherModel.deleteItemsFromDatabase(
- context, ItemInfoMatcher.ofPackages(removedPackages, mUser));
- LauncherModel.deleteItemsFromDatabase(
- context, ItemInfoMatcher.ofComponents(removedComponents, mUser));
+ getModelWriter().deleteItemsFromDatabase(
+ ItemInfoMatcher.ofPackages(removedPackages, mUser));
+ getModelWriter().deleteItemsFromDatabase(
+ ItemInfoMatcher.ofComponents(removedComponents, mUser));
// Remove any queued items from the install queue
InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index ba7112f..d8a429c 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -104,7 +104,7 @@
bindUpdatedShortcuts(updatedShortcutInfos, removedShortcutInfos, mUser);
if (!removedShortcutInfos.isEmpty()) {
- LauncherModel.deleteItemsFromDatabase(context, removedShortcutInfos);
+ getModelWriter().deleteItemsFromDatabase(removedShortcutInfos);
}
if (mUpdateIdMap) {
diff --git a/src/com/android/launcher3/model/UserLockStateChangedTask.java b/src/com/android/launcher3/model/UserLockStateChangedTask.java
index 25f2f9d..363f1ee 100644
--- a/src/com/android/launcher3/model/UserLockStateChangedTask.java
+++ b/src/com/android/launcher3/model/UserLockStateChangedTask.java
@@ -95,7 +95,7 @@
}
bindUpdatedShortcuts(updatedShortcutInfos, deletedShortcutInfos, mUser);
if (!deletedShortcutInfos.isEmpty()) {
- LauncherModel.deleteItemsFromDatabase(context, deletedShortcutInfos);
+ getModelWriter().deleteItemsFromDatabase(deletedShortcutInfos);
}
// Remove shortcut id map for that user
diff --git a/src/com/android/launcher3/notification/NotificationFooterLayout.java b/src/com/android/launcher3/notification/NotificationFooterLayout.java
index 58789f6..57ec5d1 100644
--- a/src/com/android/launcher3/notification/NotificationFooterLayout.java
+++ b/src/com/android/launcher3/notification/NotificationFooterLayout.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Rect;
@@ -30,8 +31,8 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
-import com.android.launcher3.LauncherViewPropertyAnimator;
import com.android.launcher3.R;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.popup.PopupContainerWithArrow;
@@ -154,10 +155,9 @@
Rect fromBounds = sTempRect;
firstNotification.getGlobalVisibleRect(fromBounds);
float scale = (float) toBounds.height() / fromBounds.height();
- Animator moveAndScaleIcon = new LauncherViewPropertyAnimator(firstNotification)
- .translationY(toBounds.top - fromBounds.top
- + (fromBounds.height() * scale - fromBounds.height()) / 2)
- .scaleX(scale).scaleY(scale);
+ Animator moveAndScaleIcon = LauncherAnimUtils.ofPropertyValuesHolder(firstNotification,
+ new PropertyListBuilder().scale(scale).translationY(toBounds.top - fromBounds.top
+ + (fromBounds.height() * scale - fromBounds.height()) / 2).build());
moveAndScaleIcon.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -172,7 +172,7 @@
- (mOverflowNotifications.isEmpty() ? 0 : 1);
for (int i = 1; i < numIcons; i++) {
final View child = mIconRow.getChildAt(i);
- Animator shiftChild = new LauncherViewPropertyAnimator(child).translationX(-gapWidth);
+ Animator shiftChild = ObjectAnimator.ofFloat(child, TRANSLATION_X, -gapWidth);
shiftChild.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
index 639447d..c9b3940 100644
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ b/src/com/android/launcher3/notification/NotificationItemView.java
@@ -83,12 +83,20 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mMainView.getNotificationInfo() == null) {
+ // The notification hasn't been populated yet.
+ return false;
+ }
getParent().requestDisallowInterceptTouchEvent(true);
return mSwipeHelper.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (mMainView.getNotificationInfo() == null) {
+ // The notification hasn't been populated yet.
+ return false;
+ }
return mSwipeHelper.onTouchEvent(ev) || super.onTouchEvent(ev);
}
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 206bb31..a627d23 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -40,7 +40,7 @@
* A {@link NotificationListenerService} that sends updates to its
* {@link NotificationsChangedListener} when notifications are posted or canceled,
* as well and when this service first connects. An instance of NotificationListener,
- * and its methods for getting notifications, can be obtained via {@link #getInstance()}.
+ * and its methods for getting notifications, can be obtained via {@link #getInstanceIfConnected()}.
*/
public class NotificationListener extends NotificationListenerService {
@@ -50,6 +50,7 @@
private static NotificationListener sNotificationListenerInstance = null;
private static NotificationsChangedListener sNotificationsChangedListener;
+ private static boolean sIsConnected;
private final Handler mWorkerHandler;
private final Handler mUiHandler;
@@ -65,8 +66,9 @@
mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
break;
case MSG_NOTIFICATION_FULL_REFRESH:
- final List<StatusBarNotification> activeNotifications
- = filterNotifications(getActiveNotifications());
+ final List<StatusBarNotification> activeNotifications = sIsConnected
+ ? filterNotifications(getActiveNotifications())
+ : new ArrayList<StatusBarNotification>();
mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget();
break;
}
@@ -80,9 +82,9 @@
switch (message.what) {
case MSG_NOTIFICATION_POSTED:
if (sNotificationsChangedListener != null) {
- Pair<PackageUserKey, String> pair
- = (Pair<PackageUserKey, String>) message.obj;
- sNotificationsChangedListener.onNotificationPosted(pair.first, pair.second);
+ NotificationPostedMsg msg = (NotificationPostedMsg) message.obj;
+ sNotificationsChangedListener.onNotificationPosted(msg.packageUserKey,
+ msg.notificationKey, msg.shouldBeFilteredOut);
}
break;
case MSG_NOTIFICATION_REMOVED:
@@ -107,10 +109,11 @@
super();
mWorkerHandler = new Handler(LauncherModel.getWorkerLooper(), mWorkerCallback);
mUiHandler = new Handler(Looper.getMainLooper(), mUiCallback);
+ sNotificationListenerInstance = this;
}
- public static @Nullable NotificationListener getInstance() {
- return sNotificationListenerInstance;
+ public static @Nullable NotificationListener getInstanceIfConnected() {
+ return sIsConnected ? sNotificationListenerInstance : null;
}
public static void setNotificationsChangedListener(NotificationsChangedListener listener) {
@@ -119,9 +122,8 @@
}
sNotificationsChangedListener = listener;
- NotificationListener notificationListener = getInstance();
- if (notificationListener != null) {
- notificationListener.onNotificationFullRefresh();
+ if (sNotificationListenerInstance != null) {
+ sNotificationListenerInstance.onNotificationFullRefresh();
}
}
@@ -132,7 +134,7 @@
@Override
public void onListenerConnected() {
super.onListenerConnected();
- sNotificationListenerInstance = this;
+ sIsConnected = true;
onNotificationFullRefresh();
}
@@ -143,29 +145,38 @@
@Override
public void onListenerDisconnected() {
super.onListenerDisconnected();
- sNotificationListenerInstance = null;
+ sIsConnected = false;
}
@Override
public void onNotificationPosted(final StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
- if (!shouldBeFilteredOut(sbn.getNotification())) {
- Pair<PackageUserKey, String> packageUserKeyAndNotificationKey
- = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey());
- mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, packageUserKeyAndNotificationKey)
- .sendToTarget();
+ mWorkerHandler.obtainMessage(MSG_NOTIFICATION_POSTED, new NotificationPostedMsg(sbn))
+ .sendToTarget();
+ }
+
+ /**
+ * An object containing data to send to MSG_NOTIFICATION_POSTED targets.
+ */
+ private class NotificationPostedMsg {
+ PackageUserKey packageUserKey;
+ String notificationKey;
+ boolean shouldBeFilteredOut;
+
+ NotificationPostedMsg(StatusBarNotification sbn) {
+ packageUserKey = PackageUserKey.fromNotification(sbn);
+ notificationKey = sbn.getKey();
+ shouldBeFilteredOut = shouldBeFilteredOut(sbn.getNotification());
}
}
@Override
public void onNotificationRemoved(final StatusBarNotification sbn) {
super.onNotificationRemoved(sbn);
- if (!shouldBeFilteredOut(sbn.getNotification())) {
- Pair<PackageUserKey, String> packageUserKeyAndNotificationKey
- = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey());
- mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
- .sendToTarget();
- }
+ Pair<PackageUserKey, String> packageUserKeyAndNotificationKey
+ = new Pair<>(PackageUserKey.fromNotification(sbn), sbn.getKey());
+ mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
+ .sendToTarget();
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
@@ -206,7 +217,8 @@
}
public interface NotificationsChangedListener {
- void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey);
+ void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey,
+ boolean shouldBeFilteredOut);
void onNotificationRemoved(PackageUserKey removedPackageUserKey, String notificationKey);
void onNotificationFullRefresh(List<StatusBarNotification> activeNotifications);
}
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 6677c2f..b342525 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -18,8 +18,11 @@
import android.animation.Animator;
import android.animation.AnimatorSet;
+import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -29,7 +32,6 @@
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
-import com.android.launcher3.LauncherViewPropertyAnimator;
import com.android.launcher3.R;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -39,10 +41,13 @@
*/
public class NotificationMainView extends LinearLayout implements SwipeHelper.Callback {
+ private final ArgbEvaluator mArgbEvaluator = new ArgbEvaluator();
+
private NotificationInfo mNotificationInfo;
private TextView mTitleView;
private TextView mTextView;
private IconPalette mIconPalette;
+ private ColorDrawable mColorBackground;
public NotificationMainView(Context context) {
this(context, null, 0);
@@ -65,7 +70,8 @@
}
public void applyColors(IconPalette iconPalette) {
- setBackgroundColor(iconPalette.backgroundColor);
+ mColorBackground = new ColorDrawable(iconPalette.backgroundColor);
+ setBackground(mColorBackground);
mIconPalette = iconPalette;
}
@@ -81,7 +87,7 @@
if (animate) {
mTitleView.setAlpha(0);
mTextView.setAlpha(0);
- setBackgroundColor(mIconPalette.secondaryColor);
+ mColorBackground.setColor(mIconPalette.secondaryColor);
}
mNotificationInfo = mainNotification;
mTitleView.setText(mNotificationInfo.title);
@@ -95,16 +101,10 @@
setTag(new ItemInfo());
if (animate) {
AnimatorSet animation = LauncherAnimUtils.createAnimatorSet();
- Animator textFade = new LauncherViewPropertyAnimator(mTextView).alpha(1);
- Animator titleFade = new LauncherViewPropertyAnimator(mTitleView).alpha(1);
- ValueAnimator colorChange = ValueAnimator.ofArgb(mIconPalette.secondaryColor,
- mIconPalette.backgroundColor);
- colorChange.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator valueAnimator) {
- setBackgroundColor((Integer) valueAnimator.getAnimatedValue());
- }
- });
+ Animator textFade = ObjectAnimator.ofFloat(mTextView, View.ALPHA, 1);
+ Animator titleFade = ObjectAnimator.ofFloat(mTitleView, View.ALPHA, 1);
+ ValueAnimator colorChange = ObjectAnimator.ofObject(mColorBackground, "color",
+ mArgbEvaluator, mIconPalette.secondaryColor, mIconPalette.backgroundColor);
animation.playTogether(textFade, titleFade, colorChange);
animation.setDuration(150);
animation.start();
diff --git a/src/com/android/launcher3/pageindicators/CaretDrawable.java b/src/com/android/launcher3/pageindicators/CaretDrawable.java
index 4789f69..0a00e24 100644
--- a/src/com/android/launcher3/pageindicators/CaretDrawable.java
+++ b/src/com/android/launcher3/pageindicators/CaretDrawable.java
@@ -24,6 +24,7 @@
import android.graphics.PixelFormat;
import com.android.launcher3.R;
+import com.android.launcher3.util.Themes;
import android.graphics.drawable.Drawable;
@@ -45,14 +46,15 @@
final int strokeWidth = res.getDimensionPixelSize(R.dimen.all_apps_caret_stroke_width);
final int shadowSpread = res.getDimensionPixelSize(R.dimen.all_apps_caret_shadow_spread);
- mCaretPaint.setColor(res.getColor(R.color.all_apps_caret_color));
+ mCaretPaint.setColor(res.getColor(R.color.workspace_icon_text_color));
mCaretPaint.setAntiAlias(true);
mCaretPaint.setStrokeWidth(strokeWidth);
mCaretPaint.setStyle(Paint.Style.STROKE);
mCaretPaint.setStrokeCap(Paint.Cap.SQUARE);
mCaretPaint.setStrokeJoin(Paint.Join.MITER);
- mShadowPaint.setColor(res.getColor(R.color.all_apps_caret_shadow_color));
+ mShadowPaint.setColor(res.getColor(R.color.default_shadow_color_no_alpha));
+ mShadowPaint.setAlpha(Themes.getAlpha(context, android.R.attr.spotShadowAlpha));
mShadowPaint.setAntiAlias(true);
mShadowPaint.setStrokeWidth(strokeWidth + (shadowSpread * 2));
mShadowPaint.setStyle(Paint.Style.STROKE);
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 4f5edc9..6276c80 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -37,6 +37,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
+import com.android.launcher3.util.Themes;
/**
* {@link PageIndicator} which shows dots per page. The active page is shown with the current
@@ -111,8 +112,8 @@
mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2;
setOutlineProvider(new MyOutlineProver());
- mActiveColor = Utilities.getColorAccent(context);
- mInActiveColor = getResources().getColor(R.color.page_indicator_dot_color);
+ mActiveColor = Themes.getColorAccent(context);
+ mInActiveColor = Themes.getAttrColor(context, android.R.attr.colorControlHighlight);
mIsRtl = Utilities.isRtl(getResources());
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 7fda8b5..d34727c 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
@@ -53,12 +54,12 @@
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.LauncherViewPropertyAnimator;
import com.android.launcher3.LogAccelerateInterpolator;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
+import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
@@ -298,7 +299,7 @@
anim.setInterpolator(interpolator);
shortcutAnims.play(anim);
- Animator fadeAnim = new LauncherViewPropertyAnimator(popupItemView).alpha(1);
+ Animator fadeAnim = ObjectAnimator.ofFloat(popupItemView, View.ALPHA, 1);
fadeAnim.setInterpolator(fadeInterpolator);
// We want the shortcut to be fully opaque before the arrow starts animating.
fadeAnim.setDuration(arrowScaleDelay);
@@ -318,9 +319,8 @@
// Animate the arrow
mArrow.setScaleX(0);
mArrow.setScaleY(0);
- Animator arrowScale = new LauncherViewPropertyAnimator(mArrow).scaleX(1).scaleY(1);
+ Animator arrowScale = createArrowScaleAnim(1).setDuration(arrowScaleDuration);
arrowScale.setStartDelay(arrowScaleDelay);
- arrowScale.setDuration(arrowScaleDuration);
shortcutAnims.play(arrowScale);
mOpenCloseAnimator = shortcutAnims;
@@ -603,7 +603,7 @@
removeNotification.play(removeMargin);
}
removeNotification.play(reduceHeight);
- Animator fade = new LauncherViewPropertyAnimator(notificationView).alpha(0)
+ Animator fade = ObjectAnimator.ofFloat(notificationView, ALPHA, 0)
.setDuration(duration);
fade.addListener(new AnimatorListenerAdapter() {
@Override
@@ -620,11 +620,9 @@
removeNotification.play(fade);
final long arrowScaleDuration = getResources().getInteger(
R.integer.config_deepShortcutArrowOpenDuration);
- Animator hideArrow = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(0).scaleY(0).setDuration(arrowScaleDuration);
+ Animator hideArrow = createArrowScaleAnim(0).setDuration(arrowScaleDuration);
hideArrow.setStartDelay(0);
- Animator showArrow = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(1).scaleY(1).setDuration(arrowScaleDuration);
+ Animator showArrow = createArrowScaleAnim(1).setDuration(arrowScaleDuration);
showArrow.setStartDelay((long) (duration - arrowScaleDuration * 1.5));
removeNotification.playSequentially(hideArrow, showArrow);
removeNotification.start();
@@ -633,6 +631,10 @@
notificationView.trimNotifications(badgeInfo.getNotificationKeys());
}
+ private ObjectAnimator createArrowScaleAnim(float scale) {
+ return LauncherAnimUtils.ofPropertyValuesHolder(
+ mArrow, new PropertyListBuilder().scale(scale).build());
+ }
/**
* Animates the translationY of this container if it is open above the icon.
* If it is below the icon, the container already shifts up when the height
@@ -640,8 +642,8 @@
*/
public @Nullable Animator animateTranslationYBy(int translationY, int duration) {
if (mIsAboveIcon) {
- return new LauncherViewPropertyAnimator(this)
- .translationY(getTranslationY() + translationY).setDuration(duration);
+ return ObjectAnimator.ofFloat(this, TRANSLATION_Y, getTranslationY() + translationY)
+ .setDuration(duration);
}
return null;
}
@@ -744,7 +746,7 @@
: numOpenShortcuts - i - 1;
anim.setStartDelay(stagger * animationIndex);
- Animator fadeAnim = new LauncherViewPropertyAnimator(view).alpha(0);
+ Animator fadeAnim = ObjectAnimator.ofFloat(view, View.ALPHA, 0);
// Don't start fading until the arrow is gone.
fadeAnim.setStartDelay(stagger * animationIndex + arrowScaleDuration);
fadeAnim.setDuration(duration - arrowScaleDuration);
@@ -761,12 +763,13 @@
view.setPivotY(iconCenter.y);
float scale = ((float) mLauncher.getDeviceProfile().iconSizePx) / view.getHeight();
- LauncherViewPropertyAnimator anim2 = new LauncherViewPropertyAnimator(view)
- .scaleX(scale)
- .scaleY(scale)
- .translationX(mIconShift.x)
- .translationY(mIconShift.y);
- anim2.setDuration(DragView.VIEW_ZOOM_DURATION);
+ Animator anim2 = LauncherAnimUtils.ofPropertyValuesHolder(view,
+ new PropertyListBuilder()
+ .scale(scale)
+ .translationX(mIconShift.x)
+ .translationY(mIconShift.y)
+ .build())
+ .setDuration(DragView.VIEW_ZOOM_DURATION);
shortcutAnims.play(anim2);
}
anim.addListener(new AnimatorListenerAdapter() {
@@ -777,8 +780,7 @@
});
shortcutAnims.play(anim);
}
- Animator arrowAnim = new LauncherViewPropertyAnimator(mArrow)
- .scaleX(0).scaleY(0).setDuration(arrowScaleDuration);
+ Animator arrowAnim = createArrowScaleAnim(0).setDuration(arrowScaleDuration);
arrowAnim.setStartDelay(0);
shortcutAnims.play(arrowAnim);
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index c754fda..ee2930f 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -58,19 +58,26 @@
}
@Override
- public void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey) {
+ public void onNotificationPosted(PackageUserKey postedPackageUserKey, String notificationKey,
+ boolean shouldBeFilteredOut) {
BadgeInfo badgeInfo = mPackageUserToBadgeInfos.get(postedPackageUserKey);
- boolean notificationWasAdded; // As opposed to updated.
+ boolean notificationWasAddedOrRemoved; // As opposed to updated.
if (badgeInfo == null) {
- BadgeInfo newBadgeInfo = new BadgeInfo(postedPackageUserKey);
- newBadgeInfo.addNotificationKeyIfNotExists(notificationKey);
- mPackageUserToBadgeInfos.put(postedPackageUserKey, newBadgeInfo);
- notificationWasAdded = true;
+ if (!shouldBeFilteredOut) {
+ BadgeInfo newBadgeInfo = new BadgeInfo(postedPackageUserKey);
+ newBadgeInfo.addNotificationKeyIfNotExists(notificationKey);
+ mPackageUserToBadgeInfos.put(postedPackageUserKey, newBadgeInfo);
+ notificationWasAddedOrRemoved = true;
+ } else {
+ notificationWasAddedOrRemoved = false;
+ }
} else {
- notificationWasAdded = badgeInfo.addNotificationKeyIfNotExists(notificationKey);
+ notificationWasAddedOrRemoved = shouldBeFilteredOut
+ ? badgeInfo.removeNotificationKey(notificationKey)
+ : badgeInfo.addNotificationKeyIfNotExists(notificationKey);
}
updateLauncherIconBadges(Utilities.singletonHashSet(postedPackageUserKey),
- notificationWasAdded);
+ notificationWasAddedOrRemoved);
}
@Override
@@ -165,7 +172,7 @@
private boolean updateBadgeIcon(BadgeInfo badgeInfo) {
boolean hadNotificationToShow = badgeInfo.hasNotificationToShow();
NotificationInfo notificationInfo = null;
- NotificationListener notificationListener = NotificationListener.getInstance();
+ NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
if (notificationListener != null && badgeInfo.getNotificationKeys().size() == 1) {
StatusBarNotification[] activeNotifications = notificationListener
.getActiveNotifications(new String[] {badgeInfo.getNotificationKeys().get(0)});
@@ -215,13 +222,13 @@
/** This makes a potentially expensive binder call and should be run on a background thread. */
public List<StatusBarNotification> getStatusBarNotificationsForKeys(String[] notificationKeys) {
- NotificationListener notificationListener = NotificationListener.getInstance();
+ NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
return notificationListener == null ? Collections.EMPTY_LIST
: notificationListener.getNotificationsForKeys(notificationKeys);
}
public void cancelNotification(String notificationKey) {
- NotificationListener notificationListener = NotificationListener.getInstance();
+ NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
if (notificationListener == null) {
return;
}
diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
index af61554..577d19f 100644
--- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java
+++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
@@ -203,7 +203,7 @@
long workFolderId, int startingRank, ArrayList<ShortcutInfo> workFolderApps) {
for (ItemInfo info : workFolderApps) {
info.rank = startingRank++;
- LauncherModel.addItemToDatabase(mContext, info, workFolderId, 0, 0, 0);
+ mModel.getWriter(false).addItemToDatabase(info, workFolderId, 0, 0, 0);
}
}
diff --git a/src/com/android/launcher3/util/Themes.java b/src/com/android/launcher3/util/Themes.java
new file mode 100644
index 0000000..acd589e
--- /dev/null
+++ b/src/com/android/launcher3/util/Themes.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.view.ContextThemeWrapper;
+
+/**
+ * Various utility methods associated with theming.
+ */
+public class Themes {
+
+ public static int getColorAccent(Context context) {
+ return getAttrColor(context, android.R.attr.colorAccent);
+ }
+
+ public static int getColorPrimary(Context context, int theme) {
+ return getAttrColor(new ContextThemeWrapper(context, theme), android.R.attr.colorPrimary);
+ }
+
+ public static int getAttrColor(Context context, int attr) {
+ TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+ int colorAccent = ta.getColor(0, 0);
+ ta.recycle();
+ return colorAccent;
+ }
+
+ /**
+ * Returns the alpha corresponding to the theme attribute {@param attr}, in the range [0, 255].
+ */
+ public static int getAlpha(Context context, int attr) {
+ TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
+ float alpha = ta.getFloat(0, 0);
+ ta.recycle();
+ return (int) (255 * alpha + 0.5f);
+ }
+}
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index c723f9e..6f4c286 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -29,6 +29,7 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.PendingAddItemInfo;
+import com.android.launcher3.R;
import com.android.launcher3.Workspace;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.graphics.DragPreviewProvider;
@@ -112,6 +113,11 @@
DeviceProfile dp = launcher.getDeviceProfile();
int iconSize = dp.iconSizePx;
+ int padding = launcher.getResources()
+ .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
+ previewBounds.left += padding;
+ previewBounds.top += padding;
+
dragRegion = new Rect();
dragRegion.left = (size[0] - iconSize) / 2;
dragRegion.right = dragRegion.left + iconSize;
diff --git a/src/com/android/launcher3/widget/WidgetImageView.java b/src/com/android/launcher3/widget/WidgetImageView.java
index 1211c08..df2bcff 100644
--- a/src/com/android/launcher3/widget/WidgetImageView.java
+++ b/src/com/android/launcher3/widget/WidgetImageView.java
@@ -89,16 +89,25 @@
}
private void updateDstRectF() {
- if (mBitmap.getWidth() > getWidth()) {
- float scale = ((float) getWidth()) / mBitmap.getWidth();
- mDstRectF.set(0, 0, getWidth(), scale * mBitmap.getHeight());
+ float myWidth = getWidth();
+ float myHeight = getHeight();
+ float bitmapWidth = mBitmap.getWidth();
+
+ final float scale = bitmapWidth > myWidth ? myWidth / bitmapWidth : 1;
+ float scaledWidth = bitmapWidth * scale;
+ float scaledHeight = mBitmap.getHeight() * scale;
+
+ mDstRectF.left = (myWidth - scaledWidth) / 2;
+ mDstRectF.right = (myWidth + scaledWidth) / 2;
+
+ if (scaledHeight > myHeight) {
+ mDstRectF.top = 0;
+ mDstRectF.bottom = scaledHeight;
} else {
- mDstRectF.set(
- (getWidth() - mBitmap.getWidth()) * 0.5f,
- 0,
- (getWidth() + mBitmap.getWidth()) * 0.5f,
- mBitmap.getHeight());
+ mDstRectF.top = (myHeight - scaledHeight) / 2;
+ mDstRectF.bottom = (myHeight + scaledHeight) / 2;
}
+
if (mBadge != null) {
Rect bounds = mBadge.getBounds();
int left = Utilities.boundToRange(
diff --git a/src_config/com/android/launcher3/config/FeatureFlags.java b/src_config/com/android/launcher3/config/FeatureFlags.java
index 5c29366..7459c0c 100644
--- a/src_config/com/android/launcher3/config/FeatureFlags.java
+++ b/src_config/com/android/launcher3/config/FeatureFlags.java
@@ -42,4 +42,6 @@
public static final boolean LAUNCHER3_DIRECT_SCROLL = true;
// When enabled icons are badged with the number of notifications associated with that app.
public static final boolean BADGE_ICONS = true;
+ // When enabled, icons not supporting {@link MaskableIconDrawable} will be wrapped in this class.
+ public static final boolean LEGACY_ICON_TREATMENT = false;
}
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 763481a..24882aa 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -18,6 +18,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.launcher3.tests">
+ <uses-sdk android:targetSdkVersion="25" android:minSdkVersion="21"/>
+
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index afe8952..43030ae 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -18,6 +18,7 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.android.launcher3.tests">
+ <uses-sdk android:targetSdkVersion="25" android:minSdkVersion="21"/>
<uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
<application android:debuggable="true">
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
index 2071389..d0ba907 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -53,14 +53,6 @@
return new AddWorkspaceItemsTask(Provider.of(Arrays.asList(items))) {
@Override
- protected void addItemToDatabase(Context context, ItemInfo item,
- long screenId, int[] pos) {
- item.screenId = screenId;
- item.cellX = pos[0];
- item.cellY = pos[1];
- }
-
- @Override
protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) { }
};
}
diff --git a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
index 9b7fc6e..b9944db 100644
--- a/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
+++ b/tests/src/com/android/launcher3/model/BaseModelUpdateTaskTestCase.java
@@ -37,6 +37,7 @@
import java.util.HashMap;
import java.util.List;
+import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -54,6 +55,8 @@
public InvariantDeviceProfile idp;
public LauncherAppState appState;
+ public LauncherModel model;
+ public ModelWriter modelWriter;
public MyIconCache iconCache;
public BgDataModel bgDataModel;
@@ -70,6 +73,11 @@
callbacks = mock(Callbacks.class);
appState = mock(LauncherAppState.class);
+ model = mock(LauncherModel.class);
+ modelWriter = mock(ModelWriter.class);
+ when(appState.getModel()).thenReturn(model);
+ when(model.getWriter(anyBoolean())).thenReturn(modelWriter);
+
myUser = Process.myUserHandle();
bgDataModel = new BgDataModel();