Merge "Update storage wizard to latest UX mocks." into pi-dev am: e9b6d482cb

am: 2388fe48b5

Change-Id: If85d1fadad2ed6bce18e3d4e0949c5fc5c65508c
This commit is contained in:
Jeff Sharkey
2018-04-09 19:28:22 -07:00
committed by android-build-merger
31 changed files with 972 additions and 522 deletions

View File

@@ -1842,43 +1842,39 @@
<!-- Exported for SystemUI to launch into -->
<activity android:name=".deviceinfo.StorageWizardInit"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardFormatConfirm"
android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardFormatProgress"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrate"
android:theme="@style/SetupWizardStorageStyle"
<activity android:name=".deviceinfo.StorageWizardFormatSlow"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrateConfirm"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrateProgress"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardReady"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardMoveConfirm"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMoveProgress"
android:theme="@style/SetupWizardStorageStyle"
android:theme="@style/GlifTheme.Light"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M4,8h4L8,4L4,4v4zM10,20h4v-4h-4v4zM4,20h4v-4L4,16v4zM4,14h4v-4L4,10v4zM10,14h4v-4h-4v4zM16,4v4h4L20,4h-4zM10,8h4L14,4h-4v4zM16,14h4v-4h-4v4zM16,20h4v-4h-4v4z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33v15.33C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V5.33C17,4.6 16.4,4 15.67,4zM11,20v-5.5H9L13,7v5.5h2L11,20z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM12,8h-2L10,4h2v4zM15,8h-2L13,4h2v4zM18,8h-2L16,4h2v4z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,89 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="144dp"
android:height="144dp"
android:viewportWidth="144.0"
android:viewportHeight="144.0">
<path
android:pathData="M20.98,105C19.88,105 19,104.12 19,103.03L19,44.97C19,43.88 19.88,43 20.98,43L49.02,43C50.12,43 51,43.88 51,44.97L51,103.03C51,104.12 50.12,105 49.02,105L20.98,105Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#FFFFFF"
android:strokeWidth="1"/>
<path
android:pathData="M20.98,106C19.33,106 18,104.68 18,103.03L18,44.97C18,43.32 19.33,42 20.98,42L49.02,42C50.67,42 52,43.32 52,44.97L52,103.03C52,104.68 50.67,106 49.02,106L20.98,106Z"
android:fillType="nonZero"
android:strokeColor="#DADCE0"
android:fillColor="#00000000"
android:strokeWidth="2"/>
<path
android:pathData="M20.98,104L49.02,104C49.57,104 50,103.57 50,103.03L50,44.97C50,44.43 49.57,44 49.02,44L20.98,44C20.43,44 20,44.43 20,44.97L20,103.03C20,103.57 20.43,104 20.98,104Z"
android:fillType="nonZero"
android:strokeColor="#F1F3F4"
android:fillColor="#00000000"
android:strokeWidth="2"/>
<path
android:pathData="M79,97L159,97A1,1 0,0 1,160 98L160,106A1,1 0,0 1,159 107L79,107A1,1 0,0 1,78 106L78,98A1,1 0,0 1,79 97z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#F1F3F4"
android:strokeWidth="1"/>
<path
android:pathData="M80,98L158,98A1,1 0,0 1,159 99L159,105A1,1 0,0 1,158 106L80,106A1,1 0,0 1,79 105L79,99A1,1 0,0 1,80 98z"
android:fillType="evenOdd"
android:strokeColor="#DADCE0"
android:fillColor="#00000000"
android:strokeWidth="2"/>
<path
android:pathData="M95,37L173,37C174.1,37 175,37.9 175,39L175,97C175,98.1 174.1,99 173,99L93,99L93,39C93,37.9 93.9,37 95,37Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#F1F3F4"
android:strokeWidth="1"/>
<path
android:pathData="M94,98L173,98C173.55,98 174,97.55 174,97L174,39C174,38.45 173.55,38 173,38L95,38C94.45,38 94,38.45 94,39L94,98Z"
android:fillType="evenOdd"
android:strokeColor="#DADCE0"
android:fillColor="#00000000"
android:strokeWidth="2"/>
<path
android:pathData="M100,43L180,43A1,1 0,0 1,181 44L181,92A1,1 0,0 1,180 93L100,93A1,1 0,0 1,99 92L99,44A1,1 0,0 1,100 43z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#FFFFFF"
android:strokeWidth="1"/>
<path
android:pathData="M76.63,54L71.13,54L67.01,58.2L67,66.6C67,67.37 67.62,68 68.38,68L76.63,68C77.38,68 78,67.37 78,66.6L78,55.4C78,54.63 77.38,54 76.63,54ZM72.5,58.2L71.13,58.2L71.13,55.4L72.5,55.4L72.5,58.2ZM74.56,58.2L73.19,58.2L73.19,55.4L74.56,55.4L74.56,58.2ZM76.63,58.2L75.25,58.2L75.25,55.4L76.63,55.4L76.63,58.2Z"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="0.87"
android:fillColor="?android:attr/colorAccent"
android:strokeWidth="1"/>
<path
android:pathData="M66.99,82L63,86L66.99,90L66.99,87L74,87L74,85L66.99,85L66.99,82ZM81,80L77.01,76L77.01,79L70,79L70,81L77.01,81L77.01,84L81,80Z"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="0.87"
android:fillColor="?android:attr/colorAccent"
android:strokeWidth="1"/>
<path
android:pathData="M72,72m-71.04,0a71.04,71.04 0,1 1,142.08 0a71.04,71.04 0,1 1,-142.08 0"
android:fillType="evenOdd"
android:strokeColor="#DADCE0"
android:fillColor="#00000000"
android:strokeWidth="1.92"/>
</vector>

View File

@@ -0,0 +1,75 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="82dp"
android:height="150dp"
android:viewportWidth="82.0"
android:viewportHeight="150.0">
<path
android:pathData="M42,62L45,62L45,64L42,64L42,67L40,67L40,64L37,64L37,62L40,62L40,59L42,59L42,62Z"
android:fillAlpha="0.87"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="?android:attr/colorAccent"
android:strokeWidth="1"
android:strokeAlpha="0.87"/>
<path
android:pathData="M58.63,56L53.13,56L49.01,60.2L49,68.6C49,69.37 49.62,70 50.38,70L58.63,70C59.38,70 60,69.37 60,68.6L60,57.4C60,56.63 59.38,56 58.63,56ZM54.5,60.2L53.13,60.2L53.13,57.4L54.5,57.4L54.5,60.2ZM56.56,60.2L55.19,60.2L55.19,57.4L56.56,57.4L56.56,60.2ZM58.63,60.2L57.25,60.2L57.25,57.4L58.63,57.4L58.63,60.2Z"
android:fillAlpha="0.87"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillColor="?android:attr/colorAccent"
android:strokeWidth="1"
android:strokeAlpha="0.87"/>
<path
android:pathData="M16,77L64,77A4,4 0,0 1,68 81L68,81A4,4 0,0 1,64 85L16,85A4,4 0,0 1,12 81L12,81A4,4 0,0 1,16 77z"
android:fillAlpha="0.87"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="?android:attr/colorAccent"
android:strokeWidth="1"
android:strokeAlpha="0.87"/>
<path
android:pathData="M9,77h31v8h-31z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#DADCE0"
android:strokeWidth="1"/>
<path
android:pathData="M6,144L74,144L74,6L6,6L6,144ZM4.95,150C2.21,150 0,147.88 0,145.24L0,4.76C0,2.12 2.21,0 4.95,0L75.05,0C77.79,0 80,2.12 80,4.76L80,145.24C80,147.88 77.79,150 75.05,150L4.95,150Z"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillColor="#F1F3F4"
android:strokeWidth="1"/>
<path
android:pathData="M4.95,148L75.05,148C76.7,148 78,146.75 78,145.24L78,4.76C78,3.25 76.7,2 75.05,2L4.95,2C3.3,2 2,3.25 2,4.76L2,145.24C2,146.75 3.3,148 4.95,148ZM4.95,150C2.21,150 0,147.88 0,145.24L0,4.76C0,2.12 2.21,0 4.95,0L75.05,0C77.79,0 80,2.12 80,4.76L80,145.24C80,147.88 77.79,150 75.05,150L4.95,150Z"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillColor="#DADCE0"
android:strokeWidth="1"/>
<path
android:pathData="M80,58L80,58C81.1,58 82,58.9 82,60L82,76C82,77.1 81.1,78 80,78L80,58Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#DADCE0"
android:strokeWidth="1"/>
<path
android:pathData="M80,32L80,32C81.1,32 82,32.9 82,34L82,40C82,41.1 81.1,42 80,42L80,32Z"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:fillColor="#DADCE0"
android:strokeWidth="1"/>
</vector>

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2018 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M6.99,11L3,15l3.99,4v-3H14v-2H6.99v-3zM21,9l-3.99,-4v3H10v2h7.01v3L21,9z"
android:fillColor="#000000"/>
</vector>

View File

@@ -0,0 +1,57 @@
<?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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_v2_checklist" />
<TextView
android:id="@+id/storage_wizard_migrate_v2_checklist_media"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_v2_checklist_media"
android:drawableStart="@drawable/ic_sd_card"
android:drawableTint="?android:attr/textColorSecondary"
android:drawablePadding="@dimen/suw_description_margin_bottom" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_v2_checklist_apps"
android:drawableStart="@drawable/ic_apps_alt"
android:drawableTint="?android:attr/textColorSecondary"
android:drawablePadding="@dimen/suw_description_margin_bottom" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_v2_checklist_battery"
android:drawableStart="@drawable/ic_battery_charging_full"
android:drawableTint="?android:attr/textColorSecondary"
android:drawablePadding="@dimen/suw_description_margin_bottom" />
</LinearLayout>

View File

@@ -20,6 +20,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/storage_back_button"
style="@style/SuwGlifButton.Secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onNavigateBack"
android:visibility="gone"
android:text="@string/suw_back_button_label" />
<Space
android:layout_width="0dp"
android:layout_height="0dp"
@@ -30,6 +39,8 @@
style="@style/SuwGlifButton.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onNavigateNext"
android:visibility="gone"
android:text="@string/suw_next_button_label" />
</LinearLayout>

View File

@@ -34,18 +34,13 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/storage_wizard_second_body"
android:visibility="gone"
<FrameLayout
android:id="@+id/storage_wizard_aux"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorPrimary" />
android:visibility="gone" />
</LinearLayout>

View File

@@ -28,41 +28,111 @@
android:layout_height="match_parent"
android:orientation="vertical">
<RadioButton
android:id="@+id/storage_wizard_init_external_title"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_init_external_title" />
<TextView
android:id="@+id/storage_wizard_init_external_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/storage_wizard_init_external_summary" />
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="144dp"
android:layout_height="144dp"
android:scaleType="centerInside"
android:src="@drawable/ic_storage_wizard_internal" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="@dimen/suw_glif_margin_sides"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:text="@string/storage_wizard_init_v2_internal_title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/storage_wizard_init_v2_internal_summary" />
<Button
android:id="@+id/storage_wizard_init_internal"
style="@style/SuwGlifButton.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/storage_wizard_init_v2_internal_action"
android:onClick="onNavigateInternal" />
</LinearLayout>
</LinearLayout>
<RadioButton
android:id="@+id/storage_wizard_init_internal_title"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_init_internal_title" />
<TextView
android:id="@+id/storage_wizard_init_internal_summary"
android:orientation="horizontal"
android:gravity="center_vertical">
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:background="@android:color/black"
android:backgroundTint="?android:attr/textColorTertiary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="@string/storage_wizard_init_v2_or"
android:textColor="?android:attr/textColorTertiary"
android:textAllCaps="true" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:background="@android:color/black"
android:backgroundTint="?android:attr/textColorTertiary" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/storage_wizard_init_internal_summary" />
android:layout_marginTop="@dimen/suw_description_margin_top"
android:orientation="horizontal"
android:gravity="center_vertical">
<ImageView
android:layout_width="144dp"
android:layout_height="144dp"
android:scaleType="centerInside"
android:src="@drawable/ic_storage_wizard_external" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="@dimen/suw_glif_margin_sides"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:text="@string/storage_wizard_init_v2_external_title" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/suw_description_margin_bottom"
android:textColor="?android:attr/textColorSecondary"
android:text="@string/storage_wizard_init_v2_external_summary" />
<Button
android:id="@+id/storage_wizard_init_external"
style="@style/SuwGlifButton.Primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/storage_wizard_init_v2_external_action"
android:onClick="onNavigateExternal" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@@ -1,61 +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.
-->
<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/storage_wizard_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorPrimary" />
<RadioButton
android:id="@+id/storage_wizard_migrate_now"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_now" />
<RadioButton
android:id="@+id/storage_wizard_migrate_later"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:text="@string/storage_wizard_migrate_later" />
</LinearLayout>
</com.android.setupwizardlib.GlifLayout>

View File

@@ -40,7 +40,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorSecondary" />
<TextView
@@ -49,8 +48,14 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorPrimary" />
android:textColor="?android:attr/textColorPrimary"
android:visibility="gone" />
<FrameLayout
android:id="@+id/storage_wizard_aux"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
</LinearLayout>

View File

@@ -34,7 +34,6 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/suw_description_margin_top"
android:lineSpacingExtra="@dimen/suw_description_line_spacing_extra"
android:textAppearance="@android:style/TextAppearance.Material.Body1"
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>

View File

@@ -376,9 +376,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="SetupWizardStorageStyle" parent="@style/SuwThemeGlif.Light">
</style>
<style name="PreviewPagerPageIndicator">
<item name="dotGap">8dp</item>
<item name="pageIndicatorColor">?android:attr/colorControlNormal</item>

View File

@@ -16,6 +16,11 @@
package com.android.settings.deviceinfo;
import static android.os.storage.DiskInfo.EXTRA_DISK_ID;
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_FORGET_UUID;
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_PRIVATE;
import android.content.Intent;
import android.os.Bundle;
import android.os.storage.DiskInfo;
@@ -30,8 +35,8 @@ import android.widget.Button;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
public class PrivateVolumeFormat extends InstrumentedPreferenceFragment {
private VolumeInfo mVolume;
@@ -65,9 +70,9 @@ public class PrivateVolumeFormat extends InstrumentedPreferenceFragment {
@Override
public void onClick(View v) {
final Intent intent = new Intent(getActivity(), StorageWizardFormatProgress.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORGET_UUID, mVolume.getFsUuid());
intent.putExtra(EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(EXTRA_FORMAT_PRIVATE, false);
intent.putExtra(EXTRA_FORMAT_FORGET_UUID, mVolume.getFsUuid());
startActivity(intent);
getActivity().finish();
}

View File

@@ -18,7 +18,6 @@ package com.android.settings.deviceinfo;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
@@ -223,19 +222,12 @@ public class PublicVolumeSettings extends SettingsPreferenceFragment {
@Override
public boolean onPreferenceTreeClick(Preference pref) {
final Context context = getActivity();
if (pref == mMount) {
new MountTask(context, mVolume).execute();
new MountTask(getActivity(), mVolume).execute();
} else if (pref == mFormatPublic) {
final Intent intent = new Intent(context, StorageWizardFormatConfirm.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
startActivity(intent);
StorageWizardFormatConfirm.showPublic(getActivity(), mDisk.getId());
} else if (pref == mFormatPrivate) {
final Intent intent = new Intent(context, StorageWizardFormatConfirm.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, true);
startActivity(intent);
StorageWizardFormatConfirm.showPrivate(getActivity(), mDisk.getId());
}
return super.onPreferenceTreeClick(pref);

View File

@@ -16,12 +16,14 @@
package com.android.settings.deviceinfo;
import static android.os.storage.DiskInfo.EXTRA_DISK_ID;
import static android.os.storage.VolumeInfo.EXTRA_VOLUME_ID;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.annotation.LayoutRes;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.SystemClock;
@@ -31,12 +33,15 @@ import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settingslib.Utils;
import com.android.setupwizardlib.GlifLayout;
import java.text.NumberFormat;
@@ -44,11 +49,17 @@ import java.util.List;
import java.util.Objects;
public abstract class StorageWizardBase extends Activity {
protected static final String EXTRA_FORMAT_FORGET_UUID = "format_forget_uuid";
protected static final String EXTRA_FORMAT_PRIVATE = "format_private";
protected static final String EXTRA_FORMAT_SLOW = "format_slow";
protected static final String EXTRA_MIGRATE_SKIP = "migrate_skip";
protected StorageManager mStorage;
protected VolumeInfo mVolume;
protected DiskInfo mDisk;
private Button mBack;
private Button mNext;
@Override
@@ -57,12 +68,12 @@ public abstract class StorageWizardBase extends Activity {
mStorage = getSystemService(StorageManager.class);
final String volumeId = getIntent().getStringExtra(VolumeInfo.EXTRA_VOLUME_ID);
final String volumeId = getIntent().getStringExtra(EXTRA_VOLUME_ID);
if (!TextUtils.isEmpty(volumeId)) {
mVolume = mStorage.findVolumeById(volumeId);
}
final String diskId = getIntent().getStringExtra(DiskInfo.EXTRA_DISK_ID);
final String diskId = getIntent().getStringExtra(EXTRA_DISK_ID);
if (!TextUtils.isEmpty(diskId)) {
mDisk = mStorage.findDiskById(diskId);
} else if (mVolume != null) {
@@ -78,13 +89,10 @@ public abstract class StorageWizardBase extends Activity {
public void setContentView(@LayoutRes int layoutResID) {
super.setContentView(layoutResID);
mNext = (Button) findViewById(R.id.storage_next_button);
mNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onNavigateNext();
}
});
mBack = requireViewById(R.id.storage_back_button);
mNext = requireViewById(R.id.storage_next_button);
setIcon(com.android.internal.R.drawable.ic_sd_card_48dp);
}
@Override
@@ -93,62 +101,109 @@ public abstract class StorageWizardBase extends Activity {
super.onDestroy();
}
protected Button getBackButton() {
return mBack;
}
protected Button getNextButton() {
return mNext;
}
protected GlifLayout getGlifLayout() {
return (GlifLayout) findViewById(R.id.setup_wizard_layout);
return requireViewById(R.id.setup_wizard_layout);
}
protected ProgressBar getProgressBar() {
return (ProgressBar) findViewById(R.id.storage_wizard_progress);
return requireViewById(R.id.storage_wizard_progress);
}
protected void setCurrentProgress(int progress) {
getProgressBar().setProgress(progress);
((TextView) findViewById(R.id.storage_wizard_progress_summary)).setText(
((TextView) requireViewById(R.id.storage_wizard_progress_summary)).setText(
NumberFormat.getPercentInstance().format((double) progress / 100));
}
protected void setHeaderText(int resId, String... args) {
protected void setHeaderText(int resId, CharSequence... args) {
final CharSequence headerText = TextUtils.expandTemplate(getText(resId), args);
getGlifLayout().setHeaderText(headerText);
setTitle(headerText);
}
protected void setBodyText(int resId, String... args) {
((TextView) findViewById(R.id.storage_wizard_body)).setText(
TextUtils.expandTemplate(getText(resId), args));
protected void setBodyText(int resId, CharSequence... args) {
final TextView body = requireViewById(R.id.storage_wizard_body);
body.setText(TextUtils.expandTemplate(getText(resId), args));
body.setVisibility(View.VISIBLE);
}
protected void setSecondaryBodyText(int resId, String... args) {
final TextView secondBody = ((TextView) findViewById(R.id.storage_wizard_second_body));
secondBody.setText(TextUtils.expandTemplate(getText(resId), args));
secondBody.setVisibility(View.VISIBLE);
protected void setAuxChecklist() {
final FrameLayout aux = requireViewById(R.id.storage_wizard_aux);
aux.addView(LayoutInflater.from(aux.getContext())
.inflate(R.layout.storage_wizard_checklist, aux, false));
aux.setVisibility(View.VISIBLE);
// Customize string based on disk
((TextView) aux.requireViewById(R.id.storage_wizard_migrate_v2_checklist_media))
.setText(TextUtils.expandTemplate(
getText(R.string.storage_wizard_migrate_v2_checklist_media),
mDisk.getShortDescription()));
}
protected static final int ILLUSTRATION_SETUP = 0;
protected static final int ILLUSTRATION_INTERNAL = 1;
protected static final int ILLUSTRATION_PORTABLE = 2;
protected void setBackButtonText(int resId, CharSequence... args) {
mBack.setText(TextUtils.expandTemplate(getText(resId), args));
mBack.setVisibility(View.VISIBLE);
}
protected void setIllustrationType(int type) {
// TODO: map type to updated icons once provided by UX
TypedArray array = obtainStyledAttributes(new int[] {android.R.attr.colorAccent});
Drawable icon = getDrawable(com.android.internal.R.drawable.ic_sd_card_48dp).mutate();
icon.setTint(array.getColor(0, 0));
array.recycle();
getGlifLayout().setIcon(icon);
protected void setNextButtonText(int resId, CharSequence... args) {
mNext.setText(TextUtils.expandTemplate(getText(resId), args));
mNext.setVisibility(View.VISIBLE);
}
protected void setIcon(int resId) {
final GlifLayout layout = getGlifLayout();
final Drawable icon = getDrawable(resId).mutate();
icon.setTint(Utils.getColorAccent(layout.getContext()));
layout.setIcon(icon);
}
protected void setKeepScreenOn(boolean keepScreenOn) {
getGlifLayout().setKeepScreenOn(keepScreenOn);
}
public void onNavigateNext() {
public void onNavigateBack(View view) {
throw new UnsupportedOperationException();
}
public void onNavigateNext(View view) {
throw new UnsupportedOperationException();
}
private void copyStringExtra(Intent from, Intent to, String key) {
if (from.hasExtra(key) && !to.hasExtra(key)) {
to.putExtra(key, from.getStringExtra(key));
}
}
private void copyBooleanExtra(Intent from, Intent to, String key) {
if (from.hasExtra(key) && !to.hasExtra(key)) {
to.putExtra(key, from.getBooleanExtra(key, false));
}
}
@Override
public void startActivity(Intent intent) {
final Intent from = getIntent();
final Intent to = intent;
copyStringExtra(from, to, EXTRA_DISK_ID);
copyStringExtra(from, to, EXTRA_VOLUME_ID);
copyStringExtra(from, to, EXTRA_FORMAT_FORGET_UUID);
copyBooleanExtra(from, to, EXTRA_FORMAT_PRIVATE);
copyBooleanExtra(from, to, EXTRA_FORMAT_SLOW);
copyBooleanExtra(from, to, EXTRA_MIGRATE_SKIP);
super.startActivity(intent);
}
protected VolumeInfo findFirstVolume(int type) {
return findFirstVolume(type, 1);
}

View File

@@ -16,52 +16,91 @@
package com.android.settings.deviceinfo;
import static android.os.storage.DiskInfo.EXTRA_DISK_ID;
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_FORGET_UUID;
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_PRIVATE;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class StorageWizardFormatConfirm extends StorageWizardBase {
public static final String EXTRA_FORMAT_PRIVATE = "format_private";
public static final String EXTRA_FORGET_UUID = "forget_uuid";
public class StorageWizardFormatConfirm extends InstrumentedDialogFragment {
private static final String TAG_FORMAT_WARNING = "format_warning";
private boolean mFormatPrivate;
public static void showPublic(Activity activity, String diskId) {
show(activity, diskId, null, false);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mDisk == null) {
finish();
return;
}
setContentView(R.layout.storage_wizard_generic);
public static void showPublic(Activity activity, String diskId, String forgetUuid) {
show(activity, diskId, forgetUuid, false);
}
mFormatPrivate = getIntent().getBooleanExtra(EXTRA_FORMAT_PRIVATE, false);
setIllustrationType(
mFormatPrivate ? ILLUSTRATION_INTERNAL : ILLUSTRATION_PORTABLE);
public static void showPrivate(Activity activity, String diskId) {
show(activity, diskId, null, true);
}
if (mFormatPrivate) {
setHeaderText(R.string.storage_wizard_format_confirm_title);
setBodyText(R.string.storage_wizard_format_confirm_body,
mDisk.getDescription());
} else {
setHeaderText(R.string.storage_wizard_format_confirm_public_title);
setBodyText(R.string.storage_wizard_format_confirm_public_body,
mDisk.getDescription());
}
private static void show(Activity activity, String diskId, String formatForgetUuid,
boolean formatPrivate) {
final Bundle args = new Bundle();
args.putString(EXTRA_DISK_ID, diskId);
args.putString(EXTRA_FORMAT_FORGET_UUID, formatForgetUuid);
args.putBoolean(EXTRA_FORMAT_PRIVATE, formatPrivate);
getNextButton().setText(R.string.storage_wizard_format_confirm_next);
getNextButton().setBackgroundTintList(getColorStateList(R.color.storage_wizard_button_red));
final StorageWizardFormatConfirm fragment = new StorageWizardFormatConfirm();
fragment.setArguments(args);
fragment.showAllowingStateLoss(activity.getFragmentManager(), TAG_FORMAT_WARNING);
}
@Override
public void onNavigateNext() {
final Intent intent = new Intent(this, StorageWizardFormatProgress.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(EXTRA_FORMAT_PRIVATE, mFormatPrivate);
intent.putExtra(EXTRA_FORGET_UUID, getIntent().getStringExtra(EXTRA_FORGET_UUID));
startActivity(intent);
finishAffinity();
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_VOLUME_FORMAT;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getContext();
final Bundle args = getArguments();
final String diskId = args.getString(EXTRA_DISK_ID);
final String formatForgetUuid = args.getString(EXTRA_FORMAT_FORGET_UUID);
final boolean formatPrivate = args.getBoolean(EXTRA_FORMAT_PRIVATE, false);
final DiskInfo disk = context.getSystemService(StorageManager.class)
.findDiskById(diskId);
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(TextUtils.expandTemplate(
getText(R.string.storage_wizard_format_confirm_v2_title),
disk.getShortDescription()));
builder.setMessage(TextUtils.expandTemplate(
getText(R.string.storage_wizard_format_confirm_v2_body),
disk.getDescription(),
disk.getShortDescription(),
disk.getShortDescription()));
builder.setNegativeButton(android.R.string.cancel, null);
builder.setPositiveButton(
TextUtils.expandTemplate(getText(R.string.storage_wizard_format_confirm_v2_action),
disk.getShortDescription()),
(dialog, which) -> {
final Intent intent = new Intent(context, StorageWizardFormatProgress.class);
intent.putExtra(EXTRA_DISK_ID, diskId);
intent.putExtra(EXTRA_FORMAT_FORGET_UUID, formatForgetUuid);
intent.putExtra(EXTRA_FORMAT_PRIVATE, formatPrivate);
context.startActivity(intent);
});
return builder.create();
}
}

View File

@@ -20,34 +20,26 @@ import static android.os.storage.VolumeInfo.TYPE_PRIVATE;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.IPackageMoveObserver;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IVoldTaskListener;
import android.os.PersistableBundle;
import android.os.storage.DiskInfo;
import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class StorageWizardFormatProgress extends StorageWizardBase {
private static final String TAG_SLOW_WARNING = "slow_warning";
private static final String PROP_DEBUG_STORAGE_SLOW = "sys.debug.storage_slow";
private boolean mFormatPrivate;
@@ -63,16 +55,11 @@ public class StorageWizardFormatProgress extends StorageWizardBase {
setContentView(R.layout.storage_wizard_progress);
setKeepScreenOn(true);
mFormatPrivate = getIntent().getBooleanExtra(
StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
setIllustrationType(
mFormatPrivate ? ILLUSTRATION_INTERNAL : ILLUSTRATION_PORTABLE);
mFormatPrivate = getIntent().getBooleanExtra(EXTRA_FORMAT_PRIVATE, false);
setHeaderText(R.string.storage_wizard_format_progress_title, mDisk.getDescription());
setHeaderText(R.string.storage_wizard_format_progress_title, mDisk.getShortDescription());
setBodyText(R.string.storage_wizard_format_progress_body, mDisk.getDescription());
getNextButton().setVisibility(View.GONE);
mTask = (PartitionTask) getLastNonConfigurationInstance();
if (mTask == null) {
mTask = new PartitionTask();
@@ -198,93 +185,29 @@ public class StorageWizardFormatProgress extends StorageWizardBase {
// changes.
Log.d(TAG, "New volume took " + mPrivateBench + "ms to run benchmark");
if (mPrivateBench > 2000) {
final SlowWarningFragment dialog = new SlowWarningFragment();
dialog.showAllowingStateLoss(activity.getFragmentManager(), TAG_SLOW_WARNING);
if (mPrivateBench > 2000
|| SystemProperties.getBoolean(PROP_DEBUG_STORAGE_SLOW, false)) {
mActivity.onFormatFinishedSlow();
} else {
activity.onFormatFinished();
mActivity.onFormatFinished();
}
} else {
activity.onFormatFinished();
mActivity.onFormatFinished();
}
}
}
public static class SlowWarningFragment extends InstrumentedDialogFragment {
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DIALOG_VOLUME_SLOW_WARNING;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
final StorageWizardFormatProgress target =
(StorageWizardFormatProgress) getActivity();
final String descrip = target.getDiskDescription();
final String genericDescip = target.getGenericDiskDescription();
builder.setMessage(TextUtils.expandTemplate(getText(R.string.storage_wizard_slow_body),
descrip, genericDescip));
builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final StorageWizardFormatProgress target =
(StorageWizardFormatProgress) getActivity();
target.onFormatFinished();
}
});
return builder.create();
}
public void onFormatFinished() {
final Intent intent = new Intent(this, StorageWizardFormatSlow.class);
intent.putExtra(EXTRA_FORMAT_SLOW, false);
startActivity(intent);
finishAffinity();
}
private String getDiskDescription() {
return mDisk.getDescription();
}
private String getGenericDiskDescription() {
// TODO: move this directly to DiskInfo
if (mDisk.isSd()) {
return getString(com.android.internal.R.string.storage_sd_card);
} else if (mDisk.isUsb()) {
return getString(com.android.internal.R.string.storage_usb_drive);
} else {
return null;
}
}
private void onFormatFinished() {
final String forgetUuid = getIntent().getStringExtra(
StorageWizardFormatConfirm.EXTRA_FORGET_UUID);
if (!TextUtils.isEmpty(forgetUuid)) {
mStorage.forgetVolume(forgetUuid);
}
final boolean offerMigrate;
if (mFormatPrivate) {
// Offer to migrate only if storage is currently internal
final VolumeInfo privateVol = getPackageManager()
.getPrimaryStorageCurrentVolume();
offerMigrate = (privateVol != null
&& VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.getId()));
} else {
offerMigrate = false;
}
if (offerMigrate) {
final Intent intent = new Intent(this, StorageWizardMigrate.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
} else {
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
}
public void onFormatFinishedSlow() {
final Intent intent = new Intent(this, StorageWizardFormatSlow.class);
intent.putExtra(EXTRA_FORMAT_SLOW, true);
startActivity(intent);
finishAffinity();
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2018 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.settings.deviceinfo;
import android.content.Intent;
import android.os.Bundle;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.view.View;
import com.android.settings.R;
public class StorageWizardFormatSlow extends StorageWizardBase {
private boolean mFormatPrivate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mDisk == null) {
finish();
return;
}
setContentView(R.layout.storage_wizard_generic);
mFormatPrivate = getIntent().getBooleanExtra(EXTRA_FORMAT_PRIVATE, false);
setHeaderText(R.string.storage_wizard_slow_v2_title, mDisk.getShortDescription());
setBodyText(R.string.storage_wizard_slow_v2_body, mDisk.getDescription(),
mDisk.getShortDescription(), mDisk.getShortDescription(),
mDisk.getShortDescription());
setBackButtonText(R.string.storage_wizard_slow_v2_start_over);
setNextButtonText(R.string.storage_wizard_slow_v2_continue);
// If benchmark wasn't actually slow, skip this warning
if (!getIntent().getBooleanExtra(EXTRA_FORMAT_SLOW, false)) {
onNavigateNext(null);
}
}
@Override
public void onNavigateBack(View view) {
final Intent intent = new Intent(this, StorageWizardInit.class);
startActivity(intent);
finishAffinity();
}
@Override
public void onNavigateNext(View view) {
final String forgetUuid = getIntent().getStringExtra(EXTRA_FORMAT_FORGET_UUID);
if (!TextUtils.isEmpty(forgetUuid)) {
mStorage.forgetVolume(forgetUuid);
}
final boolean offerMigrate;
if (mFormatPrivate) {
// Offer to migrate only if storage is currently internal
final VolumeInfo privateVol = getPackageManager()
.getPrimaryStorageCurrentVolume();
offerMigrate = (privateVol != null
&& VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.getId()));
} else {
offerMigrate = false;
}
if (offerMigrate) {
final Intent intent = new Intent(this, StorageWizardMigrateConfirm.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
} else {
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
}
finishAffinity();
}
}

View File

@@ -16,29 +16,20 @@
package com.android.settings.deviceinfo;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.app.ActivityManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import android.util.DebugUtils;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import android.view.View;
import android.widget.Button;
import com.android.settings.R;
import java.io.File;
public class StorageWizardInit extends StorageWizardBase {
private RadioButton mRadioExternal;
private RadioButton mRadioInternal;
private Button mExternal;
private Button mInternal;
private boolean mIsPermittedToAdopt;
@@ -54,107 +45,46 @@ public class StorageWizardInit extends StorageWizardBase {
mIsPermittedToAdopt = UserManager.get(this).isAdminUser()
&& !ActivityManager.isUserAMonkey();
setIllustrationType(ILLUSTRATION_SETUP);
setHeaderText(R.string.storage_wizard_init_title, mDisk.getDescription());
setHeaderText(R.string.storage_wizard_init_v2_title, mDisk.getShortDescription());
mRadioExternal = (RadioButton) findViewById(R.id.storage_wizard_init_external_title);
mRadioInternal = (RadioButton) findViewById(R.id.storage_wizard_init_internal_title);
mExternal = requireViewById(R.id.storage_wizard_init_external);
mInternal = requireViewById(R.id.storage_wizard_init_internal);
mRadioExternal.setOnCheckedChangeListener(mRadioListener);
mRadioInternal.setOnCheckedChangeListener(mRadioListener);
findViewById(R.id.storage_wizard_init_external_summary).setPadding(
mRadioExternal.getCompoundPaddingLeft(), 0,
mRadioExternal.getCompoundPaddingRight(), 0);
findViewById(R.id.storage_wizard_init_internal_summary).setPadding(
mRadioExternal.getCompoundPaddingLeft(), 0,
mRadioExternal.getCompoundPaddingRight(), 0);
getNextButton().setEnabled(false);
setBackButtonText(R.string.storage_wizard_init_v2_later);
if (!mDisk.isAdoptable()) {
// If not adoptable, we only have one choice
mRadioExternal.setChecked(true);
onNavigateNext();
onNavigateExternal(null);
finish();
} else if (!mIsPermittedToAdopt) {
// TODO: Show a message about why this is disabled for guest and
// that only an admin user can adopt an sd card.
mRadioInternal.setEnabled(false);
} else if (mVolume != null && mVolume.getType() == VolumeInfo.TYPE_PUBLIC
&& mVolume.isMountedReadable()) {
// Device is mounted, so classify contents to possibly pick a
// recommended default operation.
new ClassifyTask().execute(mVolume.getPath());
mInternal.setEnabled(false);
}
}
private final OnCheckedChangeListener mRadioListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
if (buttonView == mRadioExternal) {
mRadioInternal.setChecked(false);
setIllustrationType(ILLUSTRATION_PORTABLE);
} else if (buttonView == mRadioInternal) {
mRadioExternal.setChecked(false);
setIllustrationType(ILLUSTRATION_INTERNAL);
}
getNextButton().setEnabled(true);
}
}
};
@Override
public void onNavigateNext() {
if (mRadioExternal.isChecked()) {
if (mVolume != null && mVolume.getType() == VolumeInfo.TYPE_PUBLIC
&& mVolume.getState() != VolumeInfo.STATE_UNMOUNTABLE) {
// Remember that user made decision
mStorage.setVolumeInited(mVolume.getFsUuid(), true);
public void onNavigateBack(View view) {
finish();
}
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
public void onNavigateExternal(View view) {
if (mVolume != null && mVolume.getType() == VolumeInfo.TYPE_PUBLIC
&& mVolume.getState() != VolumeInfo.STATE_UNMOUNTABLE) {
// Remember that user made decision
mStorage.setVolumeInited(mVolume.getFsUuid(), true);
} else {
// Gotta format to get there
final Intent intent = new Intent(this, StorageWizardFormatConfirm.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, false);
startActivity(intent);
}
} else if (mRadioInternal.isChecked()) {
final Intent intent = new Intent(this, StorageWizardFormatConfirm.class);
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
intent.putExtra(StorageWizardFormatConfirm.EXTRA_FORMAT_PRIVATE, true);
startActivity(intent);
} else {
// Gotta format to get there
StorageWizardFormatConfirm.showPublic(this, mDisk.getId());
}
}
/**
* Task that classifies the contents of a mounted storage device, and sets a
* recommended default operation based on result.
*/
public class ClassifyTask extends AsyncTask<File, Void, Integer> {
@Override
protected Integer doInBackground(File... params) {
int classes = Environment.classifyExternalStorageDirectory(params[0]);
Log.v(TAG, "Classified " + params[0] + " as "
+ DebugUtils.flagsToString(Environment.class, "HAS_", classes));
return classes;
}
@Override
protected void onPostExecute(Integer classes) {
if (classes == 0) {
// Empty is strong signal for adopt
mRadioInternal.setChecked(true);
} else if ((classes & (Environment.HAS_PICTURES | Environment.HAS_DCIM)) != 0) {
// Photos is strong signal for portable
mRadioExternal.setChecked(true);
}
}
public void onNavigateInternal(View view) {
StorageWizardFormatConfirm.showPrivate(this, mDisk.getId());
}
}

View File

@@ -1,94 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.deviceinfo;
import android.content.Intent;
import android.os.Bundle;
import android.os.storage.DiskInfo;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import com.android.settings.R;
public class StorageWizardMigrate extends StorageWizardBase {
private MigrateEstimateTask mEstimate;
private RadioButton mRadioNow;
private RadioButton mRadioLater;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (mDisk == null) {
finish();
return;
}
setContentView(R.layout.storage_wizard_migrate);
setIllustrationType(ILLUSTRATION_INTERNAL);
setHeaderText(R.string.storage_wizard_migrate_title, mDisk.getDescription());
setBodyText(R.string.memory_calculating_size);
mRadioNow = (RadioButton) findViewById(R.id.storage_wizard_migrate_now);
mRadioLater = (RadioButton) findViewById(R.id.storage_wizard_migrate_later);
mRadioNow.setOnCheckedChangeListener(mRadioListener);
mRadioLater.setOnCheckedChangeListener(mRadioListener);
getNextButton().setEnabled(false);
mEstimate = new MigrateEstimateTask(this) {
@Override
public void onPostExecute(String size, String time) {
setBodyText(R.string.storage_wizard_migrate_body,
mDisk.getDescription(), time, size);
}
};
mEstimate.copyFrom(getIntent());
mEstimate.execute();
}
private final OnCheckedChangeListener mRadioListener = new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
if (buttonView == mRadioNow) {
mRadioLater.setChecked(false);
} else if (buttonView == mRadioLater) {
mRadioNow.setChecked(false);
}
getNextButton().setEnabled(true);
}
}
};
@Override
public void onNavigateNext() {
if (mRadioNow.isChecked()) {
final Intent intent = new Intent(this, StorageWizardMigrateConfirm.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
mEstimate.copyTo(intent);
startActivity(intent);
} else if (mRadioLater.isChecked()) {
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk.getId());
startActivity(intent);
}
}
}

View File

@@ -28,6 +28,7 @@ import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -57,30 +58,35 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase {
return;
}
final String sourceDescrip = mStorage.getBestVolumeDescription(sourceVol);
final String targetDescrip = mStorage.getBestVolumeDescription(mVolume);
setIllustrationType(ILLUSTRATION_INTERNAL);
setHeaderText(R.string.storage_wizard_migrate_confirm_title, targetDescrip);
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_migrate_v2_title, mDisk.getShortDescription());
setBodyText(R.string.memory_calculating_size);
setSecondaryBodyText(R.string.storage_wizard_migrate_details, targetDescrip);
setAuxChecklist();
mEstimate = new MigrateEstimateTask(this) {
@Override
public void onPostExecute(String size, String time) {
setBodyText(R.string.storage_wizard_migrate_confirm_body, time, size,
sourceDescrip);
setBodyText(R.string.storage_wizard_migrate_v2_body,
mDisk.getDescription(), size, time);
}
};
mEstimate.copyFrom(getIntent());
mEstimate.execute();
getNextButton().setText(R.string.storage_wizard_migrate_confirm_next);
setBackButtonText(R.string.storage_wizard_migrate_v2_later);
setNextButtonText(R.string.storage_wizard_migrate_v2_now);
}
@Override
public void onNavigateNext() {
public void onNavigateBack(View view) {
final Intent intent = new Intent(this, StorageWizardReady.class);
intent.putExtra(EXTRA_MIGRATE_SKIP, true);
startActivity(intent);
}
@Override
public void onNavigateNext(View view) {
// Ensure that all users are unlocked so that we can move their data
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
for (UserInfo user : getSystemService(UserManager.class).getUsers()) {
@@ -134,7 +140,7 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase {
if (resultCode == RESULT_OK) {
// Credentials confirmed, so storage should be unlocked; let's
// go look for the next locked user.
onNavigateNext();
onNavigateNext(null);
} else {
// User wasn't able to confirm credentials, so we're okay
// landing back at the wizard page again, where they read

View File

@@ -16,6 +16,10 @@
package com.android.settings.deviceinfo;
import static android.content.pm.PackageManager.EXTRA_MOVE_ID;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -24,14 +28,10 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.storage.DiskInfo;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
import static android.content.pm.PackageManager.EXTRA_MOVE_ID;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
public class StorageWizardMigrateProgress extends StorageWizardBase {
private static final String ACTION_FINISH_WIZARD = "com.android.systemui.action.FINISH_WIZARD";
@@ -48,12 +48,9 @@ public class StorageWizardMigrateProgress extends StorageWizardBase {
mMoveId = getIntent().getIntExtra(EXTRA_MOVE_ID, -1);
final String descrip = mStorage.getBestVolumeDescription(mVolume);
setIllustrationType(ILLUSTRATION_INTERNAL);
setHeaderText(R.string.storage_wizard_migrate_progress_title, descrip);
setBodyText(R.string.storage_wizard_migrate_details, descrip);
getNextButton().setVisibility(View.GONE);
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_migrate_progress_v2_title);
setAuxChecklist();
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());

View File

@@ -32,6 +32,7 @@ import android.os.UserManager;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import com.android.internal.util.Preconditions;
import com.android.settings.R;
@@ -67,15 +68,15 @@ public class StorageWizardMoveConfirm extends StorageWizardBase {
final String appName = getPackageManager().getApplicationLabel(mApp).toString();
final String volumeName = mStorage.getBestVolumeDescription(mVolume);
setIllustrationType(ILLUSTRATION_INTERNAL);
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_move_confirm_title, appName);
setBodyText(R.string.storage_wizard_move_confirm_body, appName, volumeName);
getNextButton().setText(R.string.move_app);
setNextButtonText(R.string.move_app);
}
@Override
public void onNavigateNext() {
public void onNavigateNext(View view) {
// Ensure that all users are unlocked so that we can move their data
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
for (UserInfo user : getSystemService(UserManager.class).getUsers()) {
@@ -108,7 +109,7 @@ public class StorageWizardMoveConfirm extends StorageWizardBase {
if (resultCode == RESULT_OK) {
// Credentials confirmed, so storage should be unlocked; let's
// go look for the next locked user.
onNavigateNext();
onNavigateNext(null);
} else {
// User wasn't able to confirm credentials, so we're okay
// landing back at the wizard page again, where they read

View File

@@ -46,12 +46,10 @@ public class StorageWizardMoveProgress extends StorageWizardBase {
final String appName = getIntent().getStringExtra(EXTRA_TITLE);
final String volumeName = mStorage.getBestVolumeDescription(mVolume);
setIllustrationType(ILLUSTRATION_INTERNAL);
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_move_progress_title, appName);
setBodyText(R.string.storage_wizard_move_progress_body, volumeName, appName);
getNextButton().setVisibility(View.GONE);
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());
mCallback.onStatusChanged(mMoveId, getPackageManager().getMoveStatus(mMoveId), -1);

View File

@@ -18,10 +18,12 @@ package com.android.settings.deviceinfo;
import android.os.Bundle;
import android.os.storage.VolumeInfo;
import android.view.View;
import com.android.settings.R;
public class StorageWizardReady extends StorageWizardBase {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -31,27 +33,23 @@ public class StorageWizardReady extends StorageWizardBase {
}
setContentView(R.layout.storage_wizard_generic);
setHeaderText(R.string.storage_wizard_ready_title, mDisk.getDescription());
setHeaderText(R.string.storage_wizard_ready_title, mDisk.getShortDescription());
// TODO: handle mixed partition cases instead of just guessing based on
// first volume type we encounter
final VolumeInfo publicVol = findFirstVolume(VolumeInfo.TYPE_PUBLIC);
final VolumeInfo privateVol = findFirstVolume(VolumeInfo.TYPE_PRIVATE);
if (publicVol != null) {
setIllustrationType(ILLUSTRATION_PORTABLE);
setBodyText(R.string.storage_wizard_ready_external_body,
mDisk.getDescription());
} else if (privateVol != null) {
setIllustrationType(ILLUSTRATION_INTERNAL);
setBodyText(R.string.storage_wizard_ready_internal_body,
final boolean migrateSkip = getIntent().getBooleanExtra(EXTRA_MIGRATE_SKIP, false);
if (privateVol != null && !migrateSkip) {
setBodyText(R.string.storage_wizard_ready_v2_internal_body,
mDisk.getDescription(), mDisk.getShortDescription());
} else {
setBodyText(R.string.storage_wizard_ready_v2_external_body,
mDisk.getDescription());
}
getNextButton().setText(R.string.done);
setNextButtonText(R.string.done);
}
@Override
public void onNavigateNext() {
public void onNavigateNext(View view) {
finishAffinity();
}
}

View File

@@ -17,6 +17,7 @@ include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := SettingsUITests
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_MODULE_TAGS := tests

View File

@@ -15,7 +15,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settings.ui">
package="com.android.settings.ui"
android:sharedUserId="android.uid.systemui">
<application>
<uses-library android:name="android.test.runner" />
@@ -26,6 +27,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2018 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.settings.ui;
import android.content.Intent;
import android.os.SystemClock;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* Verify storage wizard flows. Temporarily enables a virtual disk which enables
* testing on all devices, regardless of physical SD card support.
*/
@RunWith(AndroidJUnit4.class)
public class StorageWizardTest {
private static final String ANDROID_PACKAGE = "android";
private static final String PACKAGE = "com.android.settings";
private static final int TIMEOUT = 5000;
private static final int TIMEOUT_LONG = 30000;
private UiDevice mDevice;
private String mDisk;
private String mVolume;
@Before
public void setUp() throws Exception {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mDevice.executeShellCommand("setprop sys.debug.storage_slow 1");
mDevice.executeShellCommand("sm set-virtual-disk true");
mDisk = getAdoptableDisk();
mDevice.executeShellCommand("sm partition " + mDisk + " public");
mVolume = getPublicVolume();
}
@After
public void tearDown() throws Exception {
// Go back to home for next test.
mDevice.pressBack();
mDevice.pressBack();
mDevice.pressHome();
mDevice.waitForIdle(TIMEOUT);
mDevice.executeShellCommand("setprop sys.debug.storage_slow 0");
mDevice.executeShellCommand("sm set-virtual-disk false");
mDevice.executeShellCommand("sm forget all");
}
/**
* Test flow for adopting a storage device as internal/adopted.
*/
@Test
public void testInternal() throws Exception {
InstrumentationRegistry.getContext().startActivity(buildInitIntent());
// Activity: pick option to use as internal
waitFor(By.res(PACKAGE, "suw_layout_title").text(containsIgnoringCase("How will you use")));
waitFor(By.res(PACKAGE, "storage_wizard_init_internal")).click();
// Dialog: acknowledge that we're formatting the card
waitFor(By.res(ANDROID_PACKAGE, "alertTitle").textContains("Format"));
waitFor(By.clickable(true).text(containsIgnoringCase("Format"))).click();
// Activity: ack storage device is slow
waitForLong(By.res(PACKAGE, "suw_layout_title").textContains("Slow"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
// Activity: choose to move content
waitForLong(By.res(PACKAGE, "suw_layout_title").textContains("Move content"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
// Activity: yay, we're done!
waitForLong(By.res(PACKAGE, "suw_layout_title").textContains("ready to use"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
}
/**
* Test flow for adopting a storage device as external/portable.
*/
@Test
public void testExternal() throws Exception {
InstrumentationRegistry.getContext().startActivity(buildInitIntent());
// Activity: pick option to use as external
waitFor(By.res(PACKAGE, "suw_layout_title").textContains("How will you use"));
waitFor(By.res(PACKAGE, "storage_wizard_init_external")).click();
// Activity: yay, we're done!
waitFor(By.res(PACKAGE, "suw_layout_title").textContains("ready to use"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
}
private UiObject2 waitFor(BySelector selector) throws UiObjectNotFoundException {
return waitFor(selector, TIMEOUT);
}
private UiObject2 waitForLong(BySelector selector) throws UiObjectNotFoundException {
return waitFor(selector, TIMEOUT_LONG);
}
private UiObject2 waitFor(BySelector selector, long timeout) throws UiObjectNotFoundException {
final UiObject2 item = mDevice.wait(Until.findObject(selector), timeout);
if (item != null) {
return item;
} else {
throw new UiObjectNotFoundException(selector.toString());
}
}
/**
* Shamelessly borrowed from AdoptableHostTest in CTS.
*/
private String getAdoptableDisk() throws IOException {
// In the case where we run multiple test we cleanup the state of the device. This
// results in the execution of sm forget all which causes the MountService to "reset"
// all its knowledge about available drives. This can cause the adoptable drive to
// become temporarily unavailable.
int attempt = 0;
String disks = mDevice.executeShellCommand("sm list-disks adoptable");
while ((disks == null || disks.isEmpty()) && attempt++ < 15) {
SystemClock.sleep(1000);
disks = mDevice.executeShellCommand("sm list-disks adoptable");
}
if (disks == null || disks.isEmpty()) {
throw new AssertionError("Devices that claim to support adoptable storage must have "
+ "adoptable media inserted during CTS to verify correct behavior");
}
return disks.split("\n")[0].trim();
}
private String getPublicVolume() throws IOException {
int attempt = 0;
String volumes = mDevice.executeShellCommand("sm list-volumes public");
while ((volumes == null || volumes.isEmpty() || !volumes.contains("mounted"))
&& attempt++ < 15) {
SystemClock.sleep(1000);
volumes = mDevice.executeShellCommand("sm list-volumes public");
}
if (volumes == null || volumes.isEmpty()) {
throw new AssertionError("Devices that claim to support adoptable storage must have "
+ "adoptable media inserted during CTS to verify correct behavior");
}
return volumes.split("[\n ]")[0].trim();
}
private Intent buildInitIntent() {
final Intent intent = new Intent().setClassName(PACKAGE,
PACKAGE + ".deviceinfo.StorageWizardInit");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume);
return intent;
}
private Pattern containsIgnoringCase(String text) {
return Pattern.compile("(?i)^.*" + text + ".*$");
}
}