Merge "Fix docs build." into lmp-dev
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 3861cc1..915e2f9 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -11,7 +11,7 @@
<activity
android:name=".DocumentsActivity"
- android:theme="@style/Theme"
+ android:theme="@style/DocumentsTheme"
android:icon="@drawable/ic_doc_text">
<intent-filter>
<action android:name="android.intent.action.OPEN_DOCUMENT" />
diff --git a/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png b/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png
index 904d525..d4ffd45 100644
--- a/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png
+++ b/packages/DocumentsUI/res/drawable-hdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png b/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png
index 068619b..4a81b6b 100644
--- a/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png
+++ b/packages/DocumentsUI/res/drawable-mdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png b/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png
index e38a868..f387132 100644
--- a/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png
+++ b/packages/DocumentsUI/res/drawable-xhdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png b/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png
index 0b332e4..c475e47 100644
--- a/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png
+++ b/packages/DocumentsUI/res/drawable-xxhdpi/ic_dir_shadow_am.9.png
Binary files differ
diff --git a/packages/DocumentsUI/res/drawable/item_activated.xml b/packages/DocumentsUI/res/drawable/item_activated.xml
index 6ffefdb..1b3f44a 100644
--- a/packages/DocumentsUI/res/drawable/item_activated.xml
+++ b/packages/DocumentsUI/res/drawable/item_activated.xml
@@ -15,7 +15,11 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_focused="true" android:state_activated="true" android:drawable="@color/accent_item_activated" />
- <item android:state_focused="false" android:state_activated="true" android:drawable="@color/accent_item_activated" />
+ <item android:state_focused="true" android:state_activated="true">
+ <color android:color="?android:attr/colorAccent" />
+ </item>
+ <item android:state_focused="false" android:state_activated="true">
+ <color android:color="?android:attr/colorAccent" />
+ </item>
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/packages/DocumentsUI/res/drawable/item_root.xml b/packages/DocumentsUI/res/drawable/item_activated_overlay.xml
similarity index 73%
rename from packages/DocumentsUI/res/drawable/item_root.xml
rename to packages/DocumentsUI/res/drawable/item_activated_overlay.xml
index 60d4ab0..83e4d7e 100644
--- a/packages/DocumentsUI/res/drawable/item_root.xml
+++ b/packages/DocumentsUI/res/drawable/item_activated_overlay.xml
@@ -15,8 +15,11 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_pressed="true" android:drawable="@color/item_root_pressed" />
- <item android:state_activated="true" android:drawable="@color/item_root_focused" />
- <item android:state_focused="true" android:drawable="@color/item_root_focused" />
+ <item android:state_focused="true" android:state_activated="true">
+ <color android:color="@color/accent_color_overlay" />
+ </item>
+ <item android:state_focused="false" android:state_activated="true">
+ <color android:color="@color/accent_color_overlay" />
+ </item>
<item android:drawable="@android:color/transparent" />
</selector>
diff --git a/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml b/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml
index 5f1e432..95af7e9 100644
--- a/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout-sw720dp-land/item_doc_list.xml
@@ -17,7 +17,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:foreground="@drawable/item_activated">
+ android:background="@drawable/item_activated">
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/DocumentsUI/res/layout-sw720dp/activity.xml b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
index 9286277..4e97f8c 100644
--- a/packages/DocumentsUI/res/layout-sw720dp/activity.xml
+++ b/packages/DocumentsUI/res/layout-sw720dp/activity.xml
@@ -17,44 +17,59 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal"
- android:baselineAligned="false">
+ android:orientation="vertical">
- <FrameLayout
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:id="@+id/dialog_roots">
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="8dp"
+ android:theme="?android:attr/actionBarTheme">
+
+ <Spinner
+ android:id="@+id/stack"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:overlapAnchor="true" />
+
+ </Toolbar>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="horizontal"
+ android:baselineAligned="false">
<FrameLayout
android:id="@+id/container_roots"
android:layout_width="250dp"
android:layout_height="match_parent" />
- <ImageView
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="0dp"
android:layout_height="match_parent"
- android:layout_gravity="end"
- android:scaleType="fitXY"
- android:src="@drawable/ic_drawer_shadow_tablet" />
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:elevation="8dp"
+ android:background="@*android:color/material_grey_50">
- </FrameLayout>
+ <com.android.documentsui.DirectoryContainerView
+ android:id="@+id/container_directory"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
- <LinearLayout
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical">
+ <FrameLayout
+ android:id="@+id/container_save"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@*android:color/material_grey_50"
+ android:elevation="8dp" />
- <com.android.documentsui.DirectoryContainerView
- android:id="@+id/container_directory"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1" />
-
- <FrameLayout
- android:id="@+id/container_save"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ </LinearLayout>
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/activity.xml b/packages/DocumentsUI/res/layout/activity.xml
index 2ef7e9c..3ba82e1 100644
--- a/packages/DocumentsUI/res/layout/activity.xml
+++ b/packages/DocumentsUI/res/layout/activity.xml
@@ -24,6 +24,23 @@
android:layout_height="match_parent"
android:orientation="vertical">
+ <Toolbar
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="8dp"
+ android:theme="?android:attr/actionBarTheme">
+
+ <Spinner
+ android:id="@+id/stack"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dp"
+ android:overlapAnchor="true" />
+
+ </Toolbar>
+
<com.android.documentsui.DirectoryContainerView
android:id="@+id/container_directory"
android:layout_width="match_parent"
@@ -33,15 +50,35 @@
<FrameLayout
android:id="@+id/container_save"
android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ android:layout_height="wrap_content"
+ android:background="@*android:color/material_grey_50"
+ android:elevation="8dp" />
</LinearLayout>
- <FrameLayout
- android:id="@+id/container_roots"
+ <LinearLayout
+ android:id="@+id/drawer_roots"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start"
- android:background="#fff" />
+ android:orientation="vertical"
+ android:elevation="16dp"
+ android:background="@*android:color/white">
+
+ <Toolbar
+ android:id="@+id/roots_toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:background="?android:attr/colorPrimary"
+ android:elevation="8dp"
+ android:theme="?android:attr/actionBarTheme" />
+
+ <FrameLayout
+ android:id="@+id/container_roots"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ </LinearLayout>
</android.support.v4.widget.DrawerLayout>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 09b50c0..ffbd3f0 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -17,7 +17,7 @@
<com.android.documentsui.DirectoryView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@drawable/ic_dir_shadow">
+ android:background="@*android:color/material_grey_50">
<TextView
android:id="@android:id/empty"
diff --git a/packages/DocumentsUI/res/layout/fragment_pick.xml b/packages/DocumentsUI/res/layout/fragment_pick.xml
index 4a2fd03..5735871 100644
--- a/packages/DocumentsUI/res/layout/fragment_pick.xml
+++ b/packages/DocumentsUI/res/layout/fragment_pick.xml
@@ -17,32 +17,16 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="horizontal"
+ android:baselineAligned="false"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
- <!-- Le sigh, this really should be an asset -->
- <View
+ <Button
+ android:id="@android:id/button1"
android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="#ccc" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:gravity="center_vertical"
- android:background="#ddd"
- android:minHeight="?android:attr/listPreferredItemHeightSmall">
-
- <Button
- android:id="@android:id/button1"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAllCaps="false"
- android:padding="8dp" />
-
- </LinearLayout>
+ android:layout_height="match_parent"
+ android:textAllCaps="false"
+ style="?android:attr/buttonBarPositiveButtonStyle" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/fragment_roots.xml b/packages/DocumentsUI/res/layout/fragment_roots.xml
index c3a3da0..2d624d8 100644
--- a/packages/DocumentsUI/res/layout/fragment_roots.xml
+++ b/packages/DocumentsUI/res/layout/fragment_roots.xml
@@ -18,4 +18,5 @@
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:divider="@drawable/ic_drawer_hairline_divider" />
+ android:paddingTop="8dp"
+ android:divider="@null" />
diff --git a/packages/DocumentsUI/res/layout/fragment_save.xml b/packages/DocumentsUI/res/layout/fragment_save.xml
index d601194..7aac620 100644
--- a/packages/DocumentsUI/res/layout/fragment_save.xml
+++ b/packages/DocumentsUI/res/layout/fragment_save.xml
@@ -17,66 +17,55 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:paddingStart="@dimen/list_item_padding"
+ android:orientation="horizontal"
+ android:baselineAligned="false"
+ android:gravity="center_vertical"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
- <!-- Le sigh, this really should be an asset -->
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="#ccc" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:baselineAligned="false"
- android:gravity="center_vertical"
- android:background="#ddd"
- android:minHeight="?android:attr/listPreferredItemHeightSmall">
+ <FrameLayout
+ android:layout_width="@dimen/icon_size"
+ android:layout_height="@dimen/icon_size"
+ android:layout_marginEnd="16dp">
<ImageView
android:id="@android:id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
+ android:layout_width="@dimen/root_icon_size"
+ android:layout_height="match_parent"
android:scaleType="centerInside"
android:contentDescription="@null" />
- <EditText
- android:id="@android:id/title"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:singleLine="true"
- android:selectAllOnFocus="true" />
+ </FrameLayout>
- <FrameLayout
+ <EditText
+ android:id="@android:id/title"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:singleLine="true"
+ android:selectAllOnFocus="true" />
+
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent">
+
+ <Button
+ android:id="@android:id/button1"
android:layout_width="wrap_content"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:text="@string/menu_save"
+ style="?android:attr/buttonBarPositiveButtonStyle" />
- <Button
- android:id="@android:id/button1"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/menu_save"
- android:textAllCaps="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:padding="8dp" />
+ <ProgressBar
+ android:id="@android:id/progress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:visibility="gone"
+ android:indeterminate="true"
+ android:padding="8dp"
+ style="?android:attr/progressBarStyle" />
- <ProgressBar
- android:id="@android:id/progress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:visibility="gone"
- android:indeterminate="true"
- android:padding="8dp"
- style="?android:attr/progressBarStyle" />
-
- </FrameLayout>
-
- </LinearLayout>
+ </FrameLayout>
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 0fc606d..4482d72 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -19,7 +19,7 @@
android:layout_height="@dimen/grid_item_height"
android:orientation="vertical"
android:background="@color/grid_item_background"
- android:foreground="@drawable/item_activated">
+ android:foreground="@drawable/item_activated_overlay">
<ImageView
android:id="@+id/icon_thumb"
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 50ed2d6..c5f1842 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -17,7 +17,7 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:foreground="@drawable/item_activated">
+ android:background="@drawable/item_activated">
<LinearLayout
android:layout_width="match_parent"
diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml
index f17c261..266b9b0 100644
--- a/packages/DocumentsUI/res/layout/item_root.xml
+++ b/packages/DocumentsUI/res/layout/item_root.xml
@@ -17,25 +17,33 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:minHeight="48dp"
+ android:paddingStart="@dimen/list_item_padding"
+ android:paddingEnd="@dimen/list_item_padding"
android:gravity="center_vertical"
android:orientation="horizontal"
android:baselineAligned="false"
- android:background="@drawable/item_root">
+ android:background="@drawable/item_activated">
- <ImageView
- android:id="@android:id/icon"
+ <FrameLayout
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
- android:layout_marginEnd="8dp"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
+ android:layout_marginEnd="16dp">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="@dimen/root_icon_size"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ </FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
android:orientation="vertical">
<TextView
@@ -45,7 +53,8 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- style="@style/TextAppearance.Medium" />
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@android:id/summary"
@@ -54,7 +63,8 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- style="@style/TextAppearance.Small" />
+ android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_root_spacer.xml b/packages/DocumentsUI/res/layout/item_root_spacer.xml
index 7d96ac8..b3beced 100644
--- a/packages/DocumentsUI/res/layout/item_root_spacer.xml
+++ b/packages/DocumentsUI/res/layout/item_root_spacer.xml
@@ -14,7 +14,15 @@
limitations under the License.
-->
-<View xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/ic_drawer_tall_divider" />
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp">
+
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?android:attr/listDivider" />
+
+</FrameLayout>
diff --git a/packages/DocumentsUI/res/layout/item_title.xml b/packages/DocumentsUI/res/layout/item_subdir.xml
similarity index 87%
rename from packages/DocumentsUI/res/layout/item_title.xml
rename to packages/DocumentsUI/res/layout/item_subdir.xml
index 6e96fb5..b2a739a 100644
--- a/packages/DocumentsUI/res/layout/item_title.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir.xml
@@ -28,6 +28,7 @@
android:id="@+id/subdir"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingEnd="8dp"
android:scaleType="centerInside"
android:visibility="gone"
android:src="@drawable/ic_subdirectory_arrow"
@@ -35,11 +36,13 @@
<TextView
android:id="@android:id/title"
- android:layout_width="match_parent"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:singleLine="true"
android:ellipsize="middle"
android:textAlignment="viewStart"
- style="@style/TextAppearance.Medium" />
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_title.xml b/packages/DocumentsUI/res/layout/item_subdir_title.xml
similarity index 63%
copy from packages/DocumentsUI/res/layout/item_title.xml
copy to packages/DocumentsUI/res/layout/item_subdir_title.xml
index 6e96fb5..4c839d0 100644
--- a/packages/DocumentsUI/res/layout/item_title.xml
+++ b/packages/DocumentsUI/res/layout/item_subdir_title.xml
@@ -15,31 +15,19 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:gravity="center_vertical"
+ android:paddingEnd="8dp"
android:orientation="horizontal"
android:baselineAligned="false">
- <ImageView
- android:id="@+id/subdir"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scaleType="centerInside"
- android:visibility="gone"
- android:src="@drawable/ic_subdirectory_arrow"
- android:contentDescription="@null" />
-
<TextView
android:id="@android:id/title"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="middle"
android:textAlignment="viewStart"
- style="@style/TextAppearance.Medium" />
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/values-sw720dp/dimens.xml b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
index 75afe01..068c806 100644
--- a/packages/DocumentsUI/res/values-sw720dp/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
@@ -21,7 +21,7 @@
<item type="dimen" name="dialog_height">90%</item>
<dimen name="grid_padding_horiz">24dp</dimen>
- <dimen name="grid_padding_vert">8dp</dimen>
+ <dimen name="grid_padding_vert">16dp</dimen>
<dimen name="grid_item_padding">8dp</dimen>
diff --git a/packages/DocumentsUI/res/values-sw720dp/styles.xml b/packages/DocumentsUI/res/values-sw720dp/styles.xml
deleted file mode 100644
index 8d31444..0000000
--- a/packages/DocumentsUI/res/values-sw720dp/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
- <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
- <item name="android:windowBackground">@*android:drawable/dialog_full_holo_light</item>
- <item name="android:colorBackgroundCacheHint">@null</item>
- <item name="android:windowIsTranslucent">true</item>
- <item name="android:windowAnimationStyle">@*android:style/Animation.DeviceDefault.Dialog</item>
- </style>
-</resources>
diff --git a/packages/DocumentsUI/res/values/colors.xml b/packages/DocumentsUI/res/values/colors.xml
index e3d7f2d..08159c4 100644
--- a/packages/DocumentsUI/res/values/colors.xml
+++ b/packages/DocumentsUI/res/values/colors.xml
@@ -15,12 +15,10 @@
-->
<resources>
- <color name="chip">#ddd</color>
- <color name="item_root_pressed">#33cccccc</color>
- <color name="item_root_focused">#66cccccc</color>
- <color name="grid_item_background">#ffe1e1e0</color>
+ <!-- Half-alpha of material_teal_500 -->
+ <color name="accent_color_overlay">#8800bcd4</color>
- <color name="accent_item_activated">#88009587</color>
+ <color name="grid_item_background">@*android:color/material_grey_300</color>
</resources>
diff --git a/packages/DocumentsUI/res/values/dimens.xml b/packages/DocumentsUI/res/values/dimens.xml
index 83a0bf4..d4d7ede 100644
--- a/packages/DocumentsUI/res/values/dimens.xml
+++ b/packages/DocumentsUI/res/values/dimens.xml
@@ -37,4 +37,6 @@
<bool name="show_as_dialog">false</bool>
<bool name="always_show_summary">false</bool>
+ <dimen name="dir_elevation">8dp</dimen>
+
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
index a416eb4..4bd6991 100644
--- a/packages/DocumentsUI/res/values/styles.xml
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -15,6 +15,29 @@
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <style name="DocumentsTheme" parent="@android:style/Theme.DeviceDefault.Light.DialogWhenLarge">
+ <item name="android:actionBarWidgetTheme">@null</item>
+ <item name="android:actionBarTheme">@*android:style/ThemeOverlay.Material.Dark.ActionBar</item>
+ <item name="android:actionBarPopupTheme">@*android:style/ThemeOverlay.Material.Light</item>
+
+ <item name="android:colorPrimaryDark">@*android:color/material_blue_grey_900</item>
+ <item name="android:colorPrimary">@*android:color/material_blue_grey_800</item>
+ <item name="android:colorAccent">@*android:color/material_teal_500</item>
+
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowNoTitle">true</item>
+
+ <item name="*android:windowFixedWidthMajor">@null</item>
+ <item name="*android:windowFixedWidthMinor">@null</item>
+ <item name="*android:windowMinWidthMajor">@null</item>
+ <item name="*android:windowMinWidthMinor">@null</item>
+ <item name="*android:windowFixedHeightMajor">80%</item>
+ <item name="*android:windowFixedHeightMinor">90%</item>
+
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
+ </style>
+
<style name="TextAppearance" />
<style name="TextAppearance.Medium">
@@ -27,14 +50,4 @@
<item name="android:textColor">?android:attr/textColorTertiary</item>
</style>
- <!-- Normally just a redirection, but this is used to make ourselves a
- dialog on large tablets -->
- <style name="Theme" parent="@android:style/Theme.DeviceDefault.Light">
- <item name="android:actionOverflowButtonStyle">@style/DarkerOverflow</item>
- </style>
-
- <style name="DarkerOverflow" parent="@android:style/Widget.DeviceDefault.Light.ActionButton.Overflow">
- <item name="android:src">@drawable/ic_menu_overflow</item>
- </style>
-
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
index 00b3c87..71ea8a9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryContainerView.java
@@ -36,14 +36,6 @@
}
@Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- setClipChildren(false);
- setClipToOutline(false);
- setClipToPadding(false);
- }
-
- @Override
protected void dispatchDraw(Canvas canvas) {
final ArrayList<View> disappearing = mDisappearingChildren;
if (mDisappearingFirst && disappearing != null) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
index c163c46..4f52a03d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryView.java
@@ -37,19 +37,6 @@
}
@Override
- public void setBackground(Drawable background) {
- final Rect rect = new Rect();
- background.getPadding(rect);
-
- final boolean insetLeft = getResources().getBoolean(R.bool.list_divider_inset_left);
- if (insetLeft) {
- super.setBackground(new InsetDrawable(background, -rect.left, 0, -rect.right, 0));
- } else {
- super.setBackground(new InsetDrawable(background, -rect.right, 0, -rect.left, 0));
- }
- }
-
- @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
@@ -63,5 +50,11 @@
public void setPosition(float position) {
mPosition = position;
setX((mWidth > 0) ? (mPosition * mWidth) : 0);
+
+ if (mPosition != 0) {
+ setTranslationZ(getResources().getDimensionPixelSize(R.dimen.dir_elevation));
+ } else {
+ setTranslationZ(0);
+ }
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index d0b6a1d..fc85a0a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -28,8 +28,6 @@
import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
-import android.app.ActionBar;
-import android.app.ActionBar.OnNavigationListener;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
@@ -39,14 +37,12 @@
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Point;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.InsetDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -55,7 +51,6 @@
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.support.v4.app.ActionBarDrawerToggle;
-import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.DrawerLayout.DrawerListener;
import android.util.Log;
@@ -64,17 +59,19 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.MenuItem.OnActionExpandListener;
-import android.view.MotionEvent;
import android.view.View;
-import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
+import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
+import android.widget.Toolbar;
import com.android.documentsui.RecentsProvider.RecentColumns;
import com.android.documentsui.RecentsProvider.ResumeColumns;
@@ -105,9 +102,14 @@
private SearchView mSearchView;
+ private Toolbar mToolbar;
+ private Spinner mToolbarStack;
+
+ private Toolbar mRootsToolbar;
+
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
- private View mRootsContainer;
+ private View mRootsDrawer;
private DirectoryContainerView mDirectoryContainer;
@@ -115,6 +117,8 @@
private boolean mIgnoreNextClose;
private boolean mIgnoreNextCollapse;
+ private boolean mSearchExpanded;
+
private RootsCache mRoots;
private State mState;
@@ -127,59 +131,31 @@
setResult(Activity.RESULT_CANCELED);
setContentView(R.layout.activity);
+ final Context context = this;
final Resources res = getResources();
mShowAsDialog = res.getBoolean(R.bool.show_as_dialog);
if (mShowAsDialog) {
- // backgroundDimAmount from theme isn't applied; do it manually
+ // Strongly define our horizontal dimension; we leave vertical as
+ // WRAP_CONTENT so that system resizes us when IME is showing.
final WindowManager.LayoutParams a = getWindow().getAttributes();
- a.dimAmount = 0.6f;
- getWindow().setAttributes(a);
- getWindow().setFlags(0, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
- getWindow().setFlags(~0, WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-
- // Inset ourselves to look like a dialog
final Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
+ a.width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
- final int width = (int) res.getFraction(R.dimen.dialog_width, size.x, size.x);
- final int height = (int) res.getFraction(R.dimen.dialog_height, size.y, size.y);
- final int insetX = (size.x - width) / 2;
- final int insetY = (size.y - height) / 2;
-
- final Drawable before = getWindow().getDecorView().getBackground();
- final Drawable after = new InsetDrawable(before, insetX, insetY, insetX, insetY);
- getWindow().getDecorView().setBackground(after);
-
- // Dismiss when touch down in the dimmed inset area
- getWindow().getDecorView().setOnTouchListener(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- final float x = event.getX();
- final float y = event.getY();
- if (x < insetX || x > v.getWidth() - insetX || y < insetY
- || y > v.getHeight() - insetY) {
- finish();
- return true;
- }
- }
- return false;
- }
- });
+ getWindow().setAttributes(a);
} else {
// Non-dialog means we have a drawer
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
- R.drawable.ic_drawer_glyph, R.string.drawer_open, R.string.drawer_close);
+ R.drawable.ic_hamburger, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerListener);
- mDrawerLayout.setDrawerShadow(R.drawable.ic_drawer_shadow, GravityCompat.START);
- mRootsContainer = findViewById(R.id.container_roots);
+ mRootsDrawer = findViewById(R.id.drawer_roots);
}
mDirectoryContainer = (DirectoryContainerView) findViewById(R.id.container_directory);
@@ -190,10 +166,23 @@
buildDefaultState();
}
+ mToolbar = (Toolbar) findViewById(R.id.toolbar);
+ mToolbar.setTitleTextAppearance(context,
+ android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
+
+ mToolbarStack = (Spinner) findViewById(R.id.stack);
+ mToolbarStack.setOnItemSelectedListener(mStackListener);
+
+ mRootsToolbar = (Toolbar) findViewById(R.id.roots_toolbar);
+ if (mRootsToolbar != null) {
+ mRootsToolbar.setTitleTextAppearance(context,
+ android.R.style.TextAppearance_DeviceDefault_Widget_ActionBar_Title);
+ }
+
// Hide roots when we're managing a specific root
if (mState.action == ACTION_MANAGE) {
if (mShowAsDialog) {
- findViewById(R.id.dialog_roots).setVisibility(View.GONE);
+ findViewById(R.id.container_roots).setVisibility(View.GONE);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
}
@@ -382,15 +371,11 @@
@Override
public void onDrawerOpened(View drawerView) {
mDrawerToggle.onDrawerOpened(drawerView);
- updateActionBar();
- invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView) {
mDrawerToggle.onDrawerClosed(drawerView);
- updateActionBar();
- invalidateOptionsMenu();
}
@Override
@@ -410,9 +395,9 @@
public void setRootsDrawerOpen(boolean open) {
if (!mShowAsDialog) {
if (open) {
- mDrawerLayout.openDrawer(mRootsContainer);
+ mDrawerLayout.openDrawer(mRootsDrawer);
} else {
- mDrawerLayout.closeDrawer(mRootsContainer);
+ mDrawerLayout.closeDrawer(mRootsDrawer);
}
}
}
@@ -421,44 +406,51 @@
if (mShowAsDialog) {
return false;
} else {
- return mDrawerLayout.isDrawerOpen(mRootsContainer);
+ return mDrawerLayout.isDrawerOpen(mRootsDrawer);
}
}
public void updateActionBar() {
- final ActionBar actionBar = getActionBar();
-
- actionBar.setDisplayShowHomeEnabled(true);
-
- final boolean showIndicator = !mShowAsDialog && (mState.action != ACTION_MANAGE);
- actionBar.setDisplayHomeAsUpEnabled(showIndicator);
- if (mDrawerToggle != null) {
- mDrawerToggle.setDrawerIndicatorEnabled(showIndicator);
- }
-
- if (isRootsDrawerOpen()) {
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- actionBar.setIcon(new ColorDrawable());
-
+ if (mRootsToolbar != null) {
if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT
|| mState.action == ACTION_OPEN_TREE) {
- actionBar.setTitle(R.string.title_open);
+ mRootsToolbar.setTitle(R.string.title_open);
} else if (mState.action == ACTION_CREATE) {
- actionBar.setTitle(R.string.title_save);
+ mRootsToolbar.setTitle(R.string.title_save);
}
- } else {
- final RootInfo root = getCurrentRoot();
- actionBar.setIcon(root != null ? root.loadIcon(this) : null);
+ }
+ final RootInfo root = getCurrentRoot();
+ final boolean showRootIcon = mShowAsDialog || (mState.action == ACTION_MANAGE);
+ if (showRootIcon) {
+ mToolbar.setNavigationIcon(root != null ? root.loadIcon(this) : null);
+ mToolbar.setNavigationOnClickListener(null);
+ } else {
+ mToolbar.setNavigationIcon(R.drawable.ic_hamburger);
+ mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setRootsDrawerOpen(true);
+ }
+ });
+ }
+
+ if (mSearchExpanded) {
+ mToolbar.setTitle(null);
+ mToolbarStack.setVisibility(View.GONE);
+ mToolbarStack.setAdapter(null);
+ } else {
if (mState.stack.size() <= 1) {
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
- actionBar.setTitle(root.title);
+ mToolbar.setTitle(root.title);
+ mToolbarStack.setVisibility(View.GONE);
+ mToolbarStack.setAdapter(null);
} else {
+ mToolbar.setTitle(null);
+ mToolbarStack.setVisibility(View.VISIBLE);
+ mToolbarStack.setAdapter(mStackAdapter);
+
mIgnoreNextNavigation = true;
- actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- actionBar.setTitle(null);
- actionBar.setListNavigationCallbacks(mStackAdapter, mStackListener);
- actionBar.setSelectedNavigationItem(mStackAdapter.getCount() - 1);
+ mToolbarStack.setSelection(mStackAdapter.getCount() - 1);
}
}
}
@@ -480,6 +472,7 @@
mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
+ mSearchExpanded = true;
mState.currentSearch = query;
mSearchView.clearFocus();
onCurrentDirectoryChanged(ANIM_NONE);
@@ -495,11 +488,14 @@
searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
+ mSearchExpanded = true;
+ updateActionBar();
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
+ mSearchExpanded = false;
if (mIgnoreNextCollapse) {
mIgnoreNextCollapse = false;
return true;
@@ -514,6 +510,7 @@
mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
@Override
public boolean onClose() {
+ mSearchExpanded = false;
if (mIgnoreNextClose) {
mIgnoreNextClose = false;
return false;
@@ -545,18 +542,6 @@
final MenuItem list = menu.findItem(R.id.menu_list);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- // Open drawer means we hide most actions
- if (isRootsDrawerOpen()) {
- createDir.setVisible(false);
- search.setVisible(false);
- sort.setVisible(false);
- grid.setVisible(false);
- list.setVisible(false);
- mIgnoreNextCollapse = true;
- search.collapseActionView();
- return true;
- }
-
sort.setVisible(cwd != null);
grid.setVisible(mState.derivedMode != MODE_GRID);
list.setVisible(mState.derivedMode != MODE_LIST);
@@ -730,7 +715,7 @@
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.item_title, parent, false);
+ .inflate(R.layout.item_subdir_title, parent, false);
}
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
@@ -743,8 +728,6 @@
title.setText(doc.displayName);
}
- // No padding when shown in actionbar
- convertView.setPadding(0, 0, 0, 0);
return convertView;
}
@@ -752,7 +735,7 @@
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.item_title, parent, false);
+ .inflate(R.layout.item_subdir, parent, false);
}
final ImageView subdir = (ImageView) convertView.findViewById(R.id.subdir);
@@ -772,20 +755,24 @@
}
};
- private OnNavigationListener mStackListener = new OnNavigationListener() {
+ private OnItemSelectedListener mStackListener = new OnItemSelectedListener() {
@Override
- public boolean onNavigationItemSelected(int itemPosition, long itemId) {
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (mIgnoreNextNavigation) {
mIgnoreNextNavigation = false;
- return false;
+ return;
}
- while (mState.stack.size() > itemPosition + 1) {
+ while (mState.stack.size() > position + 1) {
mState.stackTouched = true;
mState.stack.pop();
}
onCurrentDirectoryChanged(ANIM_UP);
- return true;
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Ignored
}
};
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d7b2a98..cfdf7cf 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3698,7 +3698,7 @@
// specified, then replace it with the existing recent task.
task = tr;
}
- mTaskPersister.notify(tr, false);
+ notifyTaskPersisterLocked(tr, false);
}
if (N >= MAX_RECENT_TASKS) {
final TaskRecord tr = mRecentTasks.remove(N - 1);
@@ -7646,7 +7646,7 @@
tr.removeTaskActivitiesLocked();
cleanUpRemovedTaskLocked(tr, flags);
if (tr.isPersistable) {
- notifyTaskPersisterLocked(tr, true);
+ notifyTaskPersisterLocked(null, true);
}
return true;
}
@@ -9089,7 +9089,11 @@
}
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
- mTaskPersister.notify(task, flush);
+ if (task != null && task.stack != null && task.stack.isHomeStack()) {
+ // Never persist the home stack.
+ return;
+ }
+ mTaskPersister.wakeup(task, flush);
}
@Override
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 38eef208..0180db3 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -39,15 +39,17 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.LinkedList;
public class TaskPersister {
static final String TAG = "TaskPersister";
static final boolean DEBUG = false;
- /** When in slow mode don't write tasks out faster than this */
- private static final long INTER_TASK_DELAY_MS = 10000;
- private static final long DEBUG_INTER_TASK_DELAY_MS = 5000;
+ /** When not flushing don't write out files faster than this */
+ private static final long INTER_WRITE_DELAY_MS = 500;
+
+ /** When not flushing delay this long before writing the first file out. This gives the next
+ * task being launched a chance to load its resources without this occupying IO bandwidth. */
+ private static final long PRE_TASK_DELAY_MS = 3000;
private static final String RECENTS_FILENAME = "_task";
private static final String TASKS_DIRNAME = "recent_tasks";
@@ -63,10 +65,34 @@
private final ActivityManagerService mService;
private final ActivityStackSupervisor mStackSupervisor;
- private boolean mRecentsChanged = false;
+ /** Value determines write delay mode as follows:
+ * < 0 We are Flushing. No delays between writes until the image queue is drained and all
+ * tasks needing persisting are written to disk. There is no delay between writes.
+ * == 0 We are Idle. Next writes will be delayed by #PRE_TASK_DELAY_MS.
+ * > 0 We are Actively writing. Next write will be at this time. Subsequent writes will be
+ * delayed by #INTER_WRITE_DELAY_MS. */
+ private long mNextWriteTime = 0;
private final LazyTaskWriterThread mLazyTaskWriterThread;
+ private static class WriteQueueItem {}
+ private static class TaskWriteQueueItem extends WriteQueueItem {
+ final TaskRecord mTask;
+ TaskWriteQueueItem(TaskRecord task) {
+ mTask = task;
+ }
+ }
+ private static class ImageWriteQueueItem extends WriteQueueItem {
+ final String mFilename;
+ Bitmap mImage;
+ ImageWriteQueueItem(String filename, Bitmap image) {
+ mFilename = filename;
+ mImage = image;
+ }
+ }
+
+ ArrayList<WriteQueueItem> mWriteQueue = new ArrayList<WriteQueueItem>();
+
TaskPersister(File systemDir, ActivityStackSupervisor stackSupervisor) {
sTasksDir = new File(systemDir, TASKS_DIRNAME);
if (!sTasksDir.exists()) {
@@ -94,19 +120,77 @@
mLazyTaskWriterThread.start();
}
- public void notify(TaskRecord task, boolean flush) {
- if (DEBUG) Slog.d(TAG, "notify: task=" + task + " flush=" + flush +
- " Callers=" + Debug.getCallers(4));
- if (task != null) {
- task.needsPersisting = true;
- }
+ void wakeup(TaskRecord task, boolean flush) {
synchronized (this) {
- mLazyTaskWriterThread.mSlow = !flush;
- mRecentsChanged = true;
+ if (task != null) {
+ int queueNdx;
+ for (queueNdx = mWriteQueue.size() - 1; queueNdx >= 0; --queueNdx) {
+ final WriteQueueItem item = mWriteQueue.get(queueNdx);
+ if (item instanceof TaskWriteQueueItem &&
+ ((TaskWriteQueueItem) item).mTask == task) {
+ break;
+ }
+ }
+ if (queueNdx < 0) {
+ mWriteQueue.add(new TaskWriteQueueItem(task));
+ }
+ } else {
+ // Dummy.
+ mWriteQueue.add(new WriteQueueItem());
+ }
+ if (flush) {
+ mNextWriteTime = -1;
+ } else if (mNextWriteTime == 0) {
+ mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
+ }
+ if (DEBUG) Slog.d(TAG, "wakeup: task=" + task + " flush=" + flush + " mNextWriteTime="
+ + mNextWriteTime + " Callers=" + Debug.getCallers(4));
notifyAll();
}
}
+ void saveImage(Bitmap image, String filename) {
+ synchronized (this) {
+ int queueNdx;
+ for (queueNdx = mWriteQueue.size() - 1; queueNdx >= 0; --queueNdx) {
+ final WriteQueueItem item = mWriteQueue.get(queueNdx);
+ if (item instanceof ImageWriteQueueItem) {
+ ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
+ if (imageWriteQueueItem.mFilename.equals(filename)) {
+ // replace the Bitmap with the new one.
+ imageWriteQueueItem.mImage = image;
+ break;
+ }
+ }
+ }
+ if (queueNdx < 0) {
+ mWriteQueue.add(new ImageWriteQueueItem(filename, image));
+ }
+ if (mNextWriteTime == 0) {
+ mNextWriteTime = SystemClock.uptimeMillis() + PRE_TASK_DELAY_MS;
+ }
+ if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename + " now=" +
+ SystemClock.uptimeMillis() + " mNextWriteTime=" +
+ mNextWriteTime + " Callers=" + Debug.getCallers(4));
+ notifyAll();
+ }
+ }
+
+ Bitmap getThumbnail(String filename) {
+ synchronized (this) {
+ for (int queueNdx = mWriteQueue.size() - 1; queueNdx >= 0; --queueNdx) {
+ final WriteQueueItem item = mWriteQueue.get(queueNdx);
+ if (item instanceof ImageWriteQueueItem) {
+ ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
+ if (imageWriteQueueItem.mFilename.equals(filename)) {
+ return imageWriteQueueItem.mImage;
+ }
+ }
+ }
+ return null;
+ }
+ }
+
private StringWriter saveToXml(TaskRecord task) throws IOException, XmlPullParserException {
if (DEBUG) Slog.d(TAG, "saveToXml: task=" + task);
final XmlSerializer xmlSerializer = new FastXmlSerializer();
@@ -129,10 +213,6 @@
return stringWriter;
}
- void saveImage(Bitmap image, String filename) {
- mLazyTaskWriterThread.saveImage(image, filename);
- }
-
private String fileToString(File file) {
final String newline = System.lineSeparator();
try {
@@ -197,7 +277,7 @@
task);
if (task != null) {
task.isPersistable = true;
- task.needsPersisting = true;
+ mWriteQueue.add(new TaskWriteQueueItem(task));
tasks.add(task);
final int taskId = task.taskId;
recoveredTaskIds.add(taskId);
@@ -262,6 +342,8 @@
}
private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) {
+ if (DEBUG) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds=" + persistentTaskIds +
+ " files=" + files);
for (int fileNdx = 0; fileNdx < files.length; ++fileNdx) {
File file = files[fileNdx];
String filename = file.getName();
@@ -270,6 +352,7 @@
final int taskId;
try {
taskId = Integer.valueOf(filename.substring(0, taskIdEnd));
+ if (DEBUG) Slog.d(TAG, "removeObsoleteFile: Found taskId=" + taskId);
} catch (Exception e) {
Slog.wtf(TAG, "removeObsoleteFile: Can't parse file=" + file.getName());
file.delete();
@@ -295,63 +378,89 @@
}
private class LazyTaskWriterThread extends Thread {
- boolean mSlow = true;
- LinkedList<BitmapQueueEntry> mSaveImagesQueue = new LinkedList<BitmapQueueEntry>();
LazyTaskWriterThread(String name) {
super(name);
}
- class BitmapQueueEntry {
- final Bitmap mImage;
- final String mFilename;
- BitmapQueueEntry(Bitmap image, String filename) {
- mImage = image;
- mFilename = filename;
- }
- }
-
- void saveImage(Bitmap image, String filename) {
- synchronized (mSaveImagesQueue) {
- mSaveImagesQueue.add(new BitmapQueueEntry(image, filename));
- }
- TaskPersister.this.notify(null, false);
- }
-
@Override
public void run() {
ArraySet<Integer> persistentTaskIds = new ArraySet<Integer>();
while (true) {
- // If mSlow, then delay between each call to saveToXml().
+ // We can't lock mService while holding TaskPersister.this, but we don't want to
+ // call removeObsoleteFiles every time through the loop, only the last time before
+ // going to sleep. The risk is that we call removeObsoleteFiles() successively.
+ final boolean probablyDone;
synchronized (TaskPersister.this) {
+ probablyDone = mWriteQueue.isEmpty();
+ }
+ if (probablyDone) {
+ if (DEBUG) Slog.d(TAG, "Looking for obsolete files.");
+ persistentTaskIds.clear();
+ synchronized (mService) {
+ final ArrayList<TaskRecord> tasks = mService.mRecentTasks;
+ if (DEBUG) Slog.d(TAG, "mRecents=" + tasks);
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = tasks.get(taskNdx);
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task + " persistable=" +
+ task.isPersistable);
+ if (task.isPersistable && !task.stack.isHomeStack()) {
+ if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+ persistentTaskIds.add(task.taskId);
+ } else {
+ if (DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task=" + task);
+ }
+ }
+ }
+ removeObsoleteFiles(persistentTaskIds);
+ }
+
+ // If mNextWriteTime, then don't delay between each call to saveToXml().
+ final WriteQueueItem item;
+ synchronized (TaskPersister.this) {
+ if (mNextWriteTime >= 0) {
+ // The next write we don't have to wait so long.
+ mNextWriteTime = SystemClock.uptimeMillis() + INTER_WRITE_DELAY_MS;
+ if (DEBUG) Slog.d(TAG, "Next write time may be in " +
+ INTER_WRITE_DELAY_MS + " msec. (" + mNextWriteTime + ")");
+ }
+
+ while (mWriteQueue.isEmpty()) {
+ mNextWriteTime = 0; // idle.
+ try {
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting indefinitely.");
+ TaskPersister.this.wait();
+ } catch (InterruptedException e) {
+ }
+ // Invariant: mNextWriteTime is either -1 or PRE_WRITE_DELAY_MS from now.
+ }
+ item = mWriteQueue.remove(0);
+
long now = SystemClock.uptimeMillis();
- final long releaseTime =
- now + (DEBUG ? DEBUG_INTER_TASK_DELAY_MS: INTER_TASK_DELAY_MS);
- while (mSlow && now < releaseTime) {
+ if (DEBUG) Slog.d(TAG, "LazyTaskWriter: now=" + now + " mNextWriteTime=" +
+ mNextWriteTime);
+ while (now < mNextWriteTime) {
try {
if (DEBUG) Slog.d(TAG, "LazyTaskWriter: waiting " +
- (releaseTime - now));
- TaskPersister.this.wait(releaseTime - now);
+ (mNextWriteTime - now));
+ TaskPersister.this.wait(mNextWriteTime - now);
} catch (InterruptedException e) {
}
now = SystemClock.uptimeMillis();
}
+
+ // Got something to do.
}
- // Write out one bitmap that needs saving each time through.
- BitmapQueueEntry entry;
- synchronized (mSaveImagesQueue) {
- entry = mSaveImagesQueue.poll();
- // Are there any more after this one?
- mRecentsChanged |= !mSaveImagesQueue.isEmpty();
- }
- if (entry != null) {
- final String filename = entry.mFilename;
- if (DEBUG) Slog.d(TAG, "saveImage: filename=" + filename);
+ if (item instanceof ImageWriteQueueItem) {
+ ImageWriteQueueItem imageWriteQueueItem = (ImageWriteQueueItem) item;
+ final String filename = imageWriteQueueItem.mFilename;
+ final Bitmap bitmap = imageWriteQueueItem.mImage;
+ if (DEBUG) Slog.d(TAG, "writing bitmap: filename=" + filename);
FileOutputStream imageFile = null;
try {
imageFile = new FileOutputStream(new File(sImagesDir, filename));
- entry.mImage.compress(Bitmap.CompressFormat.PNG, 100, imageFile);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, imageFile);
} catch (Exception e) {
Slog.e(TAG, "saveImage: unable to save " + filename, e);
} finally {
@@ -362,79 +471,42 @@
}
}
}
- }
-
- StringWriter stringWriter = null;
- TaskRecord task = null;
- synchronized(mService) {
- final ArrayList<TaskRecord> tasks = mService.mRecentTasks;
- persistentTaskIds.clear();
- if (DEBUG) Slog.d(TAG, "mRecents=" + tasks);
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
- task = tasks.get(taskNdx);
- if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task + " persistable=" +
- task.isPersistable + " needsPersisting=" + task.needsPersisting);
- if (task.isPersistable && !task.stack.isHomeStack()) {
- if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
- persistentTaskIds.add(task.taskId);
-
- if (task.needsPersisting) {
- try {
- if (DEBUG) Slog.d(TAG, "Saving task=" + task);
- stringWriter = saveToXml(task);
- break;
- } catch (IOException e) {
- } catch (XmlPullParserException e) {
- } finally {
- task.needsPersisting = false;
- }
- }
- } else {
- if (DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task=" + task);
- }
- }
- }
-
- if (stringWriter != null) {
- // Write out xml file while not holding mService lock.
- FileOutputStream file = null;
- AtomicFile atomicFile = null;
- try {
- atomicFile = new AtomicFile(new File(sTasksDir,
- String.valueOf(task.taskId) + RECENTS_FILENAME + TASK_EXTENSION));
- file = atomicFile.startWrite();
- file.write(stringWriter.toString().getBytes());
- file.write('\n');
- atomicFile.finishWrite(file);
- } catch (IOException e) {
- if (file != null) {
- atomicFile.failWrite(file);
- }
- Slog.e(TAG, "Unable to open " + atomicFile + " for persisting. " + e);
- }
- } else {
- // Made it through the entire list and didn't find anything new that needed
- // persisting.
- if (!DEBUG) {
- if (DEBUG) Slog.d(TAG, "Calling removeObsoleteFiles persistentTaskIds=" +
- persistentTaskIds);
- removeObsoleteFiles(persistentTaskIds);
- }
-
- // Wait here for someone to call setRecentsChanged().
- synchronized (TaskPersister.this) {
- while (!mRecentsChanged) {
- if (DEBUG) Slog.d(TAG, "LazyTaskWriter: Waiting.");
+ } else if (item instanceof TaskWriteQueueItem) {
+ // Write out one task.
+ StringWriter stringWriter = null;
+ TaskRecord task = ((TaskWriteQueueItem) item).mTask;
+ if (DEBUG) Slog.d(TAG, "Writing task=" + task);
+ synchronized (mService) {
+ if (mService.mRecentTasks.contains(task)) {
+ // Still there.
try {
- TaskPersister.this.wait();
- } catch (InterruptedException e) {
+ if (DEBUG) Slog.d(TAG, "Saving task=" + task);
+ stringWriter = saveToXml(task);
+ } catch (IOException e) {
+ } catch (XmlPullParserException e) {
}
}
- mRecentsChanged = false;
- if (DEBUG) Slog.d(TAG, "LazyTaskWriter: Awake");
+ if (stringWriter != null) {
+ // Write out xml file while not holding mService lock.
+ FileOutputStream file = null;
+ AtomicFile atomicFile = null;
+ try {
+ atomicFile = new AtomicFile(new File(sTasksDir, String.valueOf(
+ task.taskId) + RECENTS_FILENAME + TASK_EXTENSION));
+ file = atomicFile.startWrite();
+ file.write(stringWriter.toString().getBytes());
+ file.write('\n');
+ atomicFile.finishWrite(file);
+ } catch (IOException e) {
+ if (file != null) {
+ atomicFile.failWrite(file);
+ }
+ Slog.e(TAG, "Unable to open " + atomicFile + " for persisting. " +
+ e);
+ }
+ }
}
}
- // Some recents file needs to be written.
}
}
}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index d6f922f..4a84941 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -122,9 +122,6 @@
* (positive) or back (negative). Absolute value indicates time. */
long mLastTimeMoved = System.currentTimeMillis();
- /** True if persistable, has changed, and has not yet been persisted */
- boolean needsPersisting = false;
-
/** Indication of what to run next when task exits. Use ActivityRecord types.
* ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
* task stack. */
@@ -362,6 +359,9 @@
void getLastThumbnail(TaskThumbnail thumbs) {
thumbs.mainThumbnail = mLastThumbnail;
thumbs.thumbnailFileDescriptor = null;
+ if (mLastThumbnail == null) {
+ thumbs.mainThumbnail = mService.mTaskPersister.getThumbnail(mFilename);
+ }
if (mLastThumbnailFile.exists()) {
try {
thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,