Merge "Fix issues in FP Settings"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index fddc22c..f47ef0d 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1022,7 +1022,7 @@
<activity android:name=".notification.ZenModeVoiceActivity"
android:theme="@android:style/Theme.Material.Light"
- android:label="@string/zen_mode_settings_title">
+ android:label="@string/zen_mode_interruptions_voice_title">
<intent-filter>
<action android:name="android.settings.VOICE_CONTROL_DO_NOT_DISTURB_MODE" />
<category android:name="android.intent.category.DEFAULT" />
diff --git a/res/anim/fab_elevation.xml b/res/anim/fab_elevation.xml
new file mode 100644
index 0000000..af75db0
--- /dev/null
+++ b/res/anim/fab_elevation.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="true" android:state_pressed="true">
+ <set>
+ <objectAnimator
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationZ"
+ android:valueTo="@dimen/fab_press_translation_z"
+ android:valueType="floatType" />
+ </set>
+ </item>
+ <item>
+ <set>
+ <objectAnimator
+ android:duration="@android:integer/config_shortAnimTime"
+ android:propertyName="translationZ"
+ android:valueTo="0"
+ android:valueType="floatType" />
+ </set>
+ </item>
+</selector>
\ No newline at end of file
diff --git a/res/drawable/bg_circle_blue.xml b/res/drawable/bg_voice_position.xml
similarity index 87%
rename from res/drawable/bg_circle_blue.xml
rename to res/drawable/bg_voice_position.xml
index 7f2cb1d..2fb29c2 100644
--- a/res/drawable/bg_circle_blue.xml
+++ b/res/drawable/bg_voice_position.xml
@@ -16,6 +16,6 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
- <solid android:color="@color/blue" />
+ android:shape="rectangle">
+ <solid android:color="@color/voice_interaction_highlight" />
</shape>
diff --git a/res/menu/zen_mode_automation.xml b/res/drawable/fab_background.xml
similarity index 67%
rename from res/menu/zen_mode_automation.xml
rename to res/drawable/fab_background.xml
index 02ec41f..a692a2a 100644
--- a/res/menu/zen_mode_automation.xml
+++ b/res/drawable/fab_background.xml
@@ -13,12 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:id="@+id/add"
- android:title="@string/zen_mode_time_add_rule"
- android:icon="@drawable/ic_menu_add_white"
- android:visible="true"
- android:showAsAction="collapseActionView|ifRoom" />
-</menu>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/fab_ripple">
+ <item>
+ <shape>
+ <solid android:color="@color/fab_shape" />
+ </shape>
+ </item>
+</ripple>
\ No newline at end of file
diff --git a/res/layout/mac_preference.xml b/res/layout/mac_preference.xml
deleted file mode 100644
index f096b07..0000000
--- a/res/layout/mac_preference.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:gravity="center_vertical"
- android:orientation="vertical"
- android:background="?android:attr/selectableItemBackground">
-
- <View
- android:layout_width="fill_parent"
- android:layout_height="@dimen/wifi_divider_height"
- android:background="@color/wifi_divider" />
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="?android:attr/listPreferredItemHeightSmall"
- android:gravity="center_vertical"
- android:background="?android:attr/selectableItemBackground">
-
- <RelativeLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingTop="6dip"
- android:paddingBottom="6dip">
-
- <TextView
- android:id="@+android:id/title"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:ellipsize="marquee"
- android:fadingEdge="horizontal" />
-
- <TextView
- android:id="@android:id/summary"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@android:id/title"
- android:layout_alignStart="@android:id/title"
- android:paddingStart="16dip"
- android:layout_marginEnd="16dip"
- android:visibility="gone"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:maxLines="4" />
-
- </RelativeLayout>
-
- <LinearLayout
- android:id="@android:id/widget_frame"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical"
- android:orientation="vertical" />
-
- </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index 6e8ad91..1412381 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -36,7 +36,7 @@
<ListView android:id="@android:id/list"
style="@style/PreferenceFragmentListSinglePane"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:paddingStart="@dimen/settings_side_margin"
android:paddingEnd="@dimen/settings_side_margin"
android:paddingTop="@dimen/dashboard_padding_top"
@@ -49,6 +49,18 @@
<include layout="@layout/loading_container" />
+ <com.android.settings.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:visibility="gone"
+ android:clickable="true"
+ android:layout_width="@dimen/fab_size"
+ android:layout_height="@dimen/fab_size"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="@dimen/fab_margin"
+ android:layout_marginBottom="@dimen/fab_margin"
+ android:elevation="@dimen/fab_elevation"
+ android:background="@drawable/fab_background" />
+
</FrameLayout>
<TextView android:id="@android:id/empty"
diff --git a/res/layout/voice_interaction.xml b/res/layout/voice_interaction.xml
index 13c4341..ed0cd1a 100644
--- a/res/layout/voice_interaction.xml
+++ b/res/layout/voice_interaction.xml
@@ -14,10 +14,20 @@
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/fragment_root"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:padding="8dp"
+ android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
-</FrameLayout>
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/voice_interaction_highlight"
+ android:id="@+id/voice_fragment_header" />
+ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/voice_fragment_root"
+ android:padding="8dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</LinearLayout>
diff --git a/res/layout/voice_item_row.xml b/res/layout/voice_item_row.xml
index 8576a57..eca5ac9 100644
--- a/res/layout/voice_item_row.xml
+++ b/res/layout/voice_item_row.xml
@@ -23,8 +23,8 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
- android:layout_marginTop="20dp"
- android:layout_marginBottom="20dp">
+ android:layout_marginTop="15dp"
+ android:layout_marginBottom="15dp">
<TextView
android:layout_width="0px"
@@ -33,10 +33,10 @@
android:id="@+id/voice_item_label" />
<TextView
- android:layout_width="100px"
- android:layout_height="100px"
+ android:layout_width="80px"
+ android:layout_height="80px"
android:gravity="center_horizontal|center_vertical"
- android:background="@drawable/bg_circle_blue"
+ android:background="@drawable/bg_voice_position"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:textStyle="bold"
android:id="@+id/voice_item_position" />
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index a26c99b..d9521db 100755
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -89,4 +89,5 @@
<dimen name="wifi_assistant_text_padding">24dp</dimen>
<dimen name="confirm_credentials_security_method_margin">72dp</dimen>
+ <dimen name="fab_margin">24dp</dimen>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0d0637c..88cd3cb 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -81,4 +81,7 @@
<color name="warning">#ff5621</color>
<color name="confirm_device_credential_dark_background">#263238</color>
+ <color name="fab_ripple">#1fffffff</color><!-- 12% white -->
+ <color name="fab_shape">#ff009688</color><!-- Teal 500 -->
+ <color name="voice_interaction_highlight">#33b5e5</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 07e6957..8a58c5c 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -239,4 +239,8 @@
<dimen name="fingerprint_ring_thickness">4dip</dimen>
<dimen name="confirm_credentials_security_method_margin">48dp</dimen>
+ <dimen name="fab_size">56dp</dimen>
+ <dimen name="fab_margin">16dp</dimen>
+ <dimen name="fab_elevation">12dp</dimen>
+ <dimen name="fab_press_translation_z">9dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4c9ce79..153492b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1444,10 +1444,6 @@
<string name="wifi_menu_scan">Scan</string>
<!-- Menu option to Wi-Fi advanced settings -->
<string name="wifi_menu_advanced">Advanced</string>
- <!-- Menu option to show app icons instead of WiFi strength [CHAR LIMIT=20]-->
- <string name="wifi_menu_apps">Show Apps</string>
- <!-- Menu option to show WiFi strength icons [CHAR LIMIT=20]-->
- <string name="wifi_menu_apps_strength">Show WiFi Strength</string>
<!-- Menu option to connect to a Wi-Fi network -->
<string name="wifi_menu_connect">Connect to network</string>
<!-- Menu option to remember a temporary Wi-Fi network -->
@@ -6113,26 +6109,41 @@
<!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when end time = next day -->
<string name="zen_mode_end_time_next_day_summary_format"><xliff:g id="formatted_time" example="7:00 AM">%s</xliff:g> next day</string>
+ <!-- [CHAR LIMIT=NONE] Zen mode voice: Activity title for interruption level -->
+ <string name="zen_mode_interruptions_voice_title">Interruptions</string>
+
+ <!-- [CHAR LIMIT=NONE] Zen mode voice: Header for interruption level -->
+ <string name="zen_mode_interruptions_voice_header">When calls and notifications arrive</string>
+
<!-- [CHAR LIMIT=NONE] Zen mode voice: Prompt read for interruption type -->
<string name="zen_mode_interruptions_voice_prompt">When would you like to be interrupted?</string>
<!-- [CHAR LIMIT=NONE] Zen mode voice: Prompt read for zen mode duration -->
<string name="zen_mode_duration_voice_prompt">For how long?</string>
+ <!-- [CHAR LIMIT=80] Zen mode voice: All interruptions -->
+ <string name="zen_mode_option_voice_all_interruptions">Always interrupt</string>
+
+ <!-- [CHAR LIMIT=NONE] Zen mode voice: Comma delimited synonyms for all interriuptions -->
+ <string name="zen_mode_option_voice_all_interruptions_synonyms">off,all,everything</string>
+
+ <!-- [CHAR LIMIT=80] Zen mode voice: Important interruptions -->
+ <string name="zen_mode_option_voice_important_interruptions">Allow only priority interruptions</string>
+
<!-- [CHAR LIMIT=NONE] Zen mode voice: Comma delimited synonyms for important interriuptions -->
- <string name="zen_mode_option_important_voice_synonyms">important,priority,priority notifications</string>
+ <string name="zen_mode_option_voice_important_synonyms">important,priority,priority notifications</string>
+
+ <!-- [CHAR LIMIT=80] Zen mode voice option: Alarms only -->
+ <string name="zen_mode_option_voice_alarms">Allow only alarms</string>
<!-- [CHAR LIMIT=NONE] Zen mode voice: Comma delimited synonyms for alarm interriuptions -->
- <string name="zen_mode_option_alarms_voice_synonyms">alarms</string>
+ <string name="zen_mode_option_voice_alarms_synonyms">alarms</string>
- <!-- [CHAR LIMIT=60] Zen mode voice: Off [CHAR LIMIT=60] -->
- <string name="zen_mode_option_off">Off</string>
-
- <!-- [CHAR LIMIT=NONE] Zen mode voice: Comma delimited synonyms for off interriuptions -->
- <string name="zen_mode_option_off_voice_synonyms">off,all,everything</string>
+ <!-- [CHAR LIMIT=80] Zen mode voice: No interruptions [CHAR LIMIT=60] -->
+ <string name="zen_mode_option_voice_no_interruptions">Don\'t interrupt</string>
<!-- [CHAR LIMIT=NONE] Zen mode voice: Comma delimited synonyms for no interriuptions -->
- <string name="zen_mode_option_no_interruptions_voice_synonyms">none,nothing,no interruptions</string>
+ <string name="zen_mode_option_voice_no_interruptions_synonyms">none,nothing,no interruptions</string>
<!-- [CHAR LIMIT=40] Zen mode voice: Label for indefinite mode duration -->
<string name="zen_mode_duration_indefinte_voice_label">Indefinitely</string>
@@ -6447,4 +6458,7 @@
<!-- Label of default app for current setting [CHAR LIMIT=40] -->
<string name="default_app">(Default)</string>
+ <!-- Title of app storage screen [CHAR LIMIT=30] -->
+ <string name="apps_storage">Apps storage</string>
+
</resources>
diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml
index f35d248..7956a6d 100644
--- a/res/xml/notification_settings.xml
+++ b/res/xml/notification_settings.xml
@@ -27,7 +27,7 @@
<!-- Media volume -->
<com.android.settings.notification.VolumeSeekBarPreference
android:key="media_volume"
- android:icon="@*android:drawable/ic_audio_vol"
+ android:icon="@*android:drawable/ic_audio_media"
android:title="@string/media_volume_option_title" />
<!-- Alarm volume -->
diff --git a/res/xml/timezones.xml b/res/xml/timezones.xml
index 440d098..b6f1f1d 100644
--- a/res/xml/timezones.xml
+++ b/res/xml/timezones.xml
@@ -33,6 +33,7 @@
<timezone id="Europe/Amsterdam"></timezone>
<timezone id="Europe/Belgrade"></timezone>
<timezone id="Europe/Brussels"></timezone>
+ <timezone id="Europe/Madrid"></timezone>
<timezone id="Europe/Sarajevo"></timezone>
<timezone id="Africa/Windhoek"></timezone>
<timezone id="Africa/Brazzaville"></timezone>
diff --git a/res/xml/wifi_advanced_settings.xml b/res/xml/wifi_advanced_settings.xml
index 1fc1cda..ed6cfbd 100644
--- a/res/xml/wifi_advanced_settings.xml
+++ b/res/xml/wifi_advanced_settings.xml
@@ -69,7 +69,7 @@
<Preference
android:key="mac_address"
android:title="@string/wifi_advanced_mac_address_title"
- android:layout="@layout/mac_preference" />
+ android:layout="@layout/wifi_advance_layout" />
<Preference
android:key="current_ip_address"
diff --git a/src/com/android/settings/InstrumentedFragment.java b/src/com/android/settings/InstrumentedFragment.java
index ff6f219..883c67c 100644
--- a/src/com/android/settings/InstrumentedFragment.java
+++ b/src/com/android/settings/InstrumentedFragment.java
@@ -27,6 +27,7 @@
public static final int VIEW_CATEGORY_UNDECLARED = 100000;
public static final int VIEW_CATEGORY_DEFAULT_APPS = VIEW_CATEGORY_UNDECLARED + 1;
+ public static final int VIEW_CATEGORY_STORAGE_APPS = VIEW_CATEGORY_UNDECLARED + 2;
/**
* Declare the view of this category.
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 9e645ab..17ff4b2 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -42,6 +42,8 @@
import android.widget.ListAdapter;
import android.widget.ListView;
+import com.android.settings.widget.FloatingActionButton;
+
/**
* Base class for Settings fragments, with some helper functions and dialog management.
*/
@@ -80,6 +82,7 @@
};
private ViewGroup mPinnedHeaderFrameLayout;
+ private FloatingActionButton mFloatingActionButton;
@Override
public void onCreate(Bundle icicle) {
@@ -101,9 +104,14 @@
Bundle savedInstanceState) {
final View root = super.onCreateView(inflater, container, savedInstanceState);
mPinnedHeaderFrameLayout = (ViewGroup) root.findViewById(R.id.pinned_header);
+ mFloatingActionButton = (FloatingActionButton) root.findViewById(R.id.fab);
return root;
}
+ public FloatingActionButton getFloatingActionButton() {
+ return mFloatingActionButton;
+ }
+
public void setPinnedHeaderView(View pinnedHeader) {
mPinnedHeaderFrameLayout.addView(pinnedHeader);
mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE);
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index e83482a..6762bfe 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -21,17 +21,23 @@
import android.app.Activity;
+import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.view.View;
import android.view.Window;
+import android.view.WindowManager;
import android.widget.TextView;
public class SetupWizardUtils {
private static final String TAG = "SetupWizardUtils";
+ public static final int DIALOG_IMMERSIVE_FLAGS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+
// Extra containing the resource name of the theme to be used
public static final String EXTRA_THEME = "theme";
public static final String THEME_HOLO = "holo";
@@ -95,6 +101,16 @@
}
}
+ public static void applyImmersiveFlags(final Dialog dialog) {
+ applyImmersiveFlags(dialog.getWindow(), DIALOG_IMMERSIVE_FLAGS);
+ }
+
+ private static void applyImmersiveFlags(final Window window, final int vis) {
+ WindowManager.LayoutParams attrs = window.getAttributes();
+ attrs.systemUiVisibility |= vis;
+ window.setAttributes(attrs);
+ }
+
public static TextView getHeader(Activity activity) {
return (TextView) activity.findViewById(R.id.title);
}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 4b80fdd..647be4d 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -23,13 +23,12 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageMoveObserver;
-import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
-import android.os.RemoteException;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
import android.text.format.Formatter;
import android.util.Log;
import android.view.View;
@@ -38,11 +37,16 @@
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
+import com.android.settings.DropDownPreference;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.applications.ApplicationsState.Callbacks;
-import com.android.settings.DropDownPreference;
+import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
public class AppStorageSettings extends AppInfoWithHeader
implements OnClickListener, Callbacks, DropDownPreference.Callback {
@@ -53,7 +57,6 @@
private static final int OP_FAILED = 2;
private static final int MSG_CLEAR_USER_DATA = 1;
private static final int MSG_CLEAR_CACHE = 3;
- private static final int MSG_PACKAGE_MOVE = 4;
// invalid size value used initially and also when size retrieval through PackageManager
// fails for whatever reason
@@ -64,13 +67,11 @@
private static final int DLG_CLEAR_DATA = DLG_BASE + 1;
private static final int DLG_CANNOT_CLEAR_DATA = DLG_BASE + 2;
- private static final int DLG_MOVE_FAILED = DLG_BASE + 3;
private static final String KEY_MOVE_PREFERENCE = "app_location_setting";
private static final String KEY_STORAGE_SETTINGS = "storage_settings";
private static final String KEY_CACHE_SETTINGS = "cache_settings";
- private CanBeOnSdCardChecker mCanBeOnSdCardChecker;
private TextView mTotalSize;
private TextView mAppSize;
private TextView mDataSize;
@@ -83,7 +84,6 @@
private Button mClearCacheButton;
private DropDownPreference mMoveDropDown;
- private boolean mMoveInProgress = false;
private boolean mCanClearData = true;
private boolean mHaveSizes = false;
@@ -97,7 +97,6 @@
private ClearCacheObserver mClearCacheObserver;
private ClearUserDataObserver mClearDataObserver;
- private PackageMoveObserver mPackageMoveObserver;
// Resource strings
private CharSequence mInvalidSizeStr;
@@ -107,7 +106,6 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mCanBeOnSdCardChecker = new CanBeOnSdCardChecker();
addPreferencesFromResource(R.xml.app_storage_settings);
setupViews();
}
@@ -166,18 +164,19 @@
@Override
public boolean onItemSelected(int pos, Object value) {
- boolean selectedExternal = (Boolean) value;
- boolean isExternal = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
- if (selectedExternal ^ isExternal) {
- if (mPackageMoveObserver == null) {
- mPackageMoveObserver = new PackageMoveObserver();
- }
- int moveFlags = selectedExternal ? PackageManager.MOVE_EXTERNAL_MEDIA
- : PackageManager.MOVE_INTERNAL;
- mMoveInProgress = true;
- refreshButtons();
- mPm.movePackage(mAppEntry.info.packageName, mPackageMoveObserver, moveFlags);
+ final Context context = getActivity();
+
+ // If not current volume, kick off move wizard
+ final VolumeInfo targetVol = (VolumeInfo) value;
+ final VolumeInfo currentVol = context.getPackageManager().getApplicationCurrentVolume(
+ mAppEntry.info);
+ if (!Objects.equals(targetVol, currentVol)) {
+ final Intent intent = new Intent(context, StorageWizardMoveConfirm.class);
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, targetVol.getId());
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppEntry.info.packageName);
+ startActivity(intent);
}
+
return true;
}
@@ -260,27 +259,17 @@
retrieveAppEntry();
refreshButtons();
refreshSizeInfo();
- boolean isExternal = (mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
- mMoveDropDown.setSelectedItem(isExternal ? 1 : 0);
+
+ final VolumeInfo currentVol = getActivity().getPackageManager()
+ .getApplicationCurrentVolume(mAppEntry.info);
+ mMoveDropDown.setSelectedValue(currentVol);
+
return true;
}
private void refreshButtons() {
- if (!mMoveInProgress) {
- initMoveDropDown();
- initDataButtons();
- } else {
- mMoveDropDown.setSummary(R.string.moving);
- mMoveDropDown.setSelectable(false);
- }
- }
-
- private void updateMoveEnabled(boolean enabled) {
- mMoveDropDown.clearItems();
- mMoveDropDown.addItem(R.string.storage_type_internal, false);
- if (enabled) {
- mMoveDropDown.addItem(R.string.storage_type_external, true);
- }
+ initMoveDropDown();
+ initDataButtons();
}
private void initDataButtons() {
@@ -310,20 +299,18 @@
}
private void initMoveDropDown() {
- if (Environment.isExternalStorageEmulated()) {
- updateMoveEnabled(false);
- return;
+ final Context context = getActivity();
+ final StorageManager storage = context.getSystemService(StorageManager.class);
+
+ final List<VolumeInfo> candidates = context.getPackageManager()
+ .getApplicationCandidateVolumes(mAppEntry.info);
+ Collections.sort(candidates, VolumeInfo.getDescriptionComparator());
+
+ mMoveDropDown.clearItems();
+ for (VolumeInfo vol : candidates) {
+ final String volDescrip = storage.getBestVolumeDescription(vol);
+ mMoveDropDown.addItem(volDescrip, vol);
}
- boolean dataOnly = (mPackageInfo == null) && (mAppEntry != null);
- boolean moveDisable = true;
- if ((mAppEntry.info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
- // Always let apps move to internal storage from sdcard.
- moveDisable = false;
- } else {
- mCanBeOnSdCardChecker.init();
- moveDisable = !mCanBeOnSdCardChecker.check(mAppEntry.info);
- }
- updateMoveEnabled(!moveDisable);
mMoveDropDown.setSelectable(!mAppControlRestricted);
}
@@ -351,21 +338,6 @@
}
}
- private void processMoveMsg(Message msg) {
- int result = msg.arg1;
- String packageName = mAppEntry.info.packageName;
- // Refresh the button attributes.
- mMoveInProgress = false;
- if (result == PackageManager.MOVE_SUCCEEDED) {
- Log.i(TAG, "Moved resources for " + packageName);
- // Refresh size information again.
- mState.requestSize(mPackageName, mUserId);
- } else {
- showDialogInner(DLG_MOVE_FAILED, result);
- }
- refreshUi();
- }
-
/*
* Private method to handle clear message notification from observer when
* the async operation from PackageManager is complete
@@ -382,24 +354,6 @@
}
}
- private CharSequence getMoveErrMsg(int errCode) {
- switch (errCode) {
- case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
- return getActivity().getString(R.string.insufficient_storage);
- case PackageManager.MOVE_FAILED_DOESNT_EXIST:
- return getActivity().getString(R.string.does_not_exist);
- case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
- return getActivity().getString(R.string.app_forward_locked);
- case PackageManager.MOVE_FAILED_INVALID_LOCATION:
- return getActivity().getString(R.string.invalid_location);
- case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
- return getActivity().getString(R.string.system_package);
- case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
- return "";
- }
- return "";
- }
-
@Override
protected AlertDialog createDialog(int id, int errorCode) {
switch (id) {
@@ -427,14 +381,6 @@
}
})
.create();
- case DLG_MOVE_FAILED:
- CharSequence msg = getActivity().getString(R.string.move_app_failed_dlg_text,
- getMoveErrMsg(errorCode));
- return new AlertDialog.Builder(getActivity())
- .setTitle(getActivity().getText(R.string.move_app_failed_dlg_title))
- .setMessage(msg)
- .setNeutralButton(R.string.dlg_ok, null)
- .create();
}
return null;
}
@@ -459,9 +405,6 @@
// Refresh size info
mState.requestSize(mPackageName, mUserId);
break;
- case MSG_PACKAGE_MOVE:
- processMoveMsg(msg);
- break;
}
}
};
@@ -508,13 +451,4 @@
mHandler.sendMessage(msg);
}
}
-
- class PackageMoveObserver extends IPackageMoveObserver.Stub {
- public void packageMoved(String packageName, int returnCode) throws RemoteException {
- final Message msg = mHandler.obtainMessage(MSG_PACKAGE_MOVE);
- msg.arg1 = returnCode;
- mHandler.sendMessage(msg);
- }
- }
-
}
diff --git a/src/com/android/settings/applications/ApplicationsState.java b/src/com/android/settings/applications/ApplicationsState.java
index 162ca77..c5124c6 100644
--- a/src/com/android/settings/applications/ApplicationsState.java
+++ b/src/com/android/settings/applications/ApplicationsState.java
@@ -54,6 +54,7 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Objects;
import java.util.regex.Pattern;
/**
@@ -295,20 +296,6 @@
}
};
- public static final AppFilter FILTER_ON_SD_CARD = new AppFilter() {
- final CanBeOnSdCardChecker mCanBeOnSdCardChecker
- = new CanBeOnSdCardChecker();
-
- public void init() {
- mCanBeOnSdCardChecker.init();
- }
-
- @Override
- public boolean filterApp(AppEntry entry) {
- return mCanBeOnSdCardChecker.check(entry.info);
- }
- };
-
public static final AppFilter FILTER_DISABLED = new AppFilter() {
public void init() {
}
@@ -349,6 +336,23 @@
}
};
+ public static class VolumeFilter implements AppFilter {
+ private final String mVolumeUuid;
+
+ public VolumeFilter(String volumeUuid) {
+ mVolumeUuid = volumeUuid;
+ }
+
+ @Override
+ public void init() {
+ }
+
+ @Override
+ public boolean filterApp(AppEntry info) {
+ return Objects.equals(info.info.volumeUuid, mVolumeUuid);
+ }
+ }
+
public static class CompoundFilter implements AppFilter {
private final AppFilter mFirstFilter;
private final AppFilter mSecondFilter;
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index b6b2b82..b675ba4 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -20,15 +20,11 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
import android.content.pm.IntentFilterVerificationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceFrameLayout;
@@ -53,19 +49,21 @@
import android.widget.ListView;
import android.widget.Spinner;
-import com.android.internal.content.PackageHelper;
import com.android.internal.logging.MetricsLogger;
+import com.android.settings.AppHeader;
import com.android.settings.HelpUtils;
import com.android.settings.InstrumentedFragment;
import com.android.settings.R;
import com.android.settings.Settings.AllApplicationsActivity;
import com.android.settings.Settings.DomainsURLsAppListActivity;
import com.android.settings.Settings.NotificationAppListActivity;
+import com.android.settings.Settings.StorageUseActivity;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.applications.ApplicationsState.AppEntry;
import com.android.settings.applications.ApplicationsState.AppFilter;
import com.android.settings.applications.ApplicationsState.CompoundFilter;
+import com.android.settings.applications.ApplicationsState.VolumeFilter;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.AppRow;
@@ -74,47 +72,6 @@
import java.util.Comparator;
import java.util.List;
-final class CanBeOnSdCardChecker {
- final IPackageManager mPm;
- int mInstallLocation;
-
- CanBeOnSdCardChecker() {
- mPm = IPackageManager.Stub.asInterface(
- ServiceManager.getService("package"));
- }
-
- void init() {
- try {
- mInstallLocation = mPm.getInstallLocation();
- } catch (RemoteException e) {
- Log.e("CanBeOnSdCardChecker", "Is Package Manager running?");
- return;
- }
- }
-
- boolean check(ApplicationInfo info) {
- boolean canBe = false;
- if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
- canBe = true;
- } else {
- if ((info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- if (info.installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL ||
- info.installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
- canBe = true;
- } else if (info.installLocation
- == PackageInfo.INSTALL_LOCATION_UNSPECIFIED) {
- if (mInstallLocation == PackageHelper.APP_INSTALL_EXTERNAL) {
- // For apps with no preference and the default value set
- // to install on sdcard.
- canBe = true;
- }
- }
- }
- }
- return canBe;
- }
-}
-
/**
* Activity to pick an application that will be used to display installation information and
* options to uninstall/delete user data for system applications. This activity
@@ -127,6 +84,12 @@
static final String TAG = "ManageApplications";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ // Intent extras.
+ public static final String EXTRA_CLASSNAME = "classname";
+ // Used for storage only.
+ public static final String EXTRA_VOLUME_UUID = "volumeUuid";
+ public static final String EXTRA_VOLUME_NAME = "volumeName";
+
private static final String EXTRA_SORT_ORDER = "sortOrder";
// attributes used as keys when passing values to InstalledAppDetails activity
@@ -226,6 +189,7 @@
public static final int LIST_TYPE_MAIN = 0;
public static final int LIST_TYPE_NOTIFICATION = 1;
public static final int LIST_TYPE_DOMAINS_URLS = 2;
+ public static final int LIST_TYPE_STORAGE = 3;
private View mRootView;
@@ -234,6 +198,8 @@
private FilterSpinnerAdapter mFilterAdapter;
private NotificationBackend mNotifBackend;
private ResetAppsHelper mResetAppsHelper;
+ private String mVolumeUuid;
+ private String mVolumeName;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -242,8 +208,8 @@
mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication());
Intent intent = getActivity().getIntent();
- String className = getArguments() != null
- ? getArguments().getString("classname") : null;
+ Bundle args = getArguments();
+ String className = args != null ? args.getString(EXTRA_CLASSNAME) : null;
if (className == null) {
className = intent.getComponent().getClassName();
}
@@ -254,6 +220,16 @@
mNotifBackend = new NotificationBackend();
} else if (className.equals(DomainsURLsAppListActivity.class.getName())) {
mListType = LIST_TYPE_DOMAINS_URLS;
+ } else if (className.equals(StorageUseActivity.class.getName())) {
+ if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
+ mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
+ mVolumeName = args.getString(EXTRA_VOLUME_NAME);
+ mListType = LIST_TYPE_STORAGE;
+ } else {
+ // No volume selected, display a normal list, sorted by size.
+ mListType = LIST_TYPE_MAIN;
+ mSortOrder = R.id.sort_order_size;
+ }
} else {
mListType = LIST_TYPE_MAIN;
}
@@ -324,7 +300,7 @@
contentParent.addView(mSpinnerHeader, 0);
mFilterAdapter.enableFilter(getDefaultFilter());
- if (mListType != LIST_TYPE_MAIN) {
+ if (mListType != LIST_TYPE_STORAGE) {
if (UserManager.get(getActivity()).getUserProfiles().size() > 1) {
mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
mFilterAdapter.enableFilter(FILTER_APPS_WORK);
@@ -336,6 +312,15 @@
mFilterAdapter.enableFilter(FILTER_APPS_PRIORITY);
mFilterAdapter.enableFilter(FILTER_APPS_SENSITIVE);
}
+ mApplications.setOverrideFilter(new VolumeFilter(mVolumeUuid));
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ if (mListType == LIST_TYPE_STORAGE) {
+ AppHeader.createAppHeader(getActivity(), null, mVolumeName, null);
+ }
}
private int getDefaultFilter() {
@@ -358,6 +343,8 @@
return MetricsLogger.MANAGE_APPLICATIONS_NOTIFICATIONS;
case LIST_TYPE_DOMAINS_URLS:
return MetricsLogger.MANAGE_DOMAIN_URLS;
+ case LIST_TYPE_STORAGE:
+ return InstrumentedFragment.VIEW_CATEGORY_STORAGE_APPS;
default:
return MetricsLogger.VIEW_UNKNOWN;
}
@@ -680,6 +667,7 @@
private int mWhichSize = SIZE_TOTAL;
CharSequence mCurFilterPrefix;
private PackageManager mPm;
+ private AppFilter mOverrideFilter;
private Filter mFilter = new Filter() {
@Override
@@ -718,6 +706,11 @@
}
}
+ public void setOverrideFilter(AppFilter overrideFilter) {
+ mOverrideFilter = overrideFilter;
+ rebuild(true);
+ }
+
public void setFilter(int filter) {
mFilterMode = filter;
rebuild(true);
@@ -774,6 +767,9 @@
mWhichSize = SIZE_INTERNAL;
}
filterObj = FILTERS[mFilterMode];
+ if (mOverrideFilter != null) {
+ filterObj = mOverrideFilter;
+ }
switch (mLastSortMode) {
case R.id.sort_order_size:
switch (mWhichSize) {
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
index dec259b..a280b2d 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeSettings.java
@@ -55,6 +55,9 @@
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settings.Settings.StorageUseActivity;
+import com.android.settings.applications.ManageApplications;
import com.android.settings.deviceinfo.StorageMeasurement.MeasurementDetails;
import com.android.settings.deviceinfo.StorageMeasurement.MeasurementReceiver;
import com.android.settings.deviceinfo.StorageSettings.MountTask;
@@ -323,9 +326,13 @@
Intent intent = null;
if (pref == mApps) {
- intent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE);
- intent.setClass(getActivity(), Settings.ManageApplicationsActivity.class);
-
+ Bundle args = new Bundle();
+ args.putString(ManageApplications.EXTRA_CLASSNAME, StorageUseActivity.class.getName());
+ args.putString(ManageApplications.EXTRA_VOLUME_UUID, mVolume.getFsUuid());
+ args.putString(ManageApplications.EXTRA_VOLUME_NAME, mVolume.getDescription());
+ intent = Utils.onBuildStartFragmentIntent(getActivity(),
+ ManageApplications.class.getName(), args, null, R.string.apps_storage, null,
+ false);
} else if (pref == mDownloads) {
intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS).putExtra(
DownloadManager.INTENT_EXTRAS_SORT_BY_SIZE, true);
diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java
index 1e33230d..74040ef 100644
--- a/src/com/android/settings/deviceinfo/StorageSettings.java
+++ b/src/com/android/settings/deviceinfo/StorageSettings.java
@@ -41,7 +41,6 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
/**
@@ -91,21 +90,6 @@
setHasOptionsMenu(true);
}
- private static final Comparator<VolumeInfo> sVolumeComparator = new Comparator<VolumeInfo>() {
- @Override
- public int compare(VolumeInfo lhs, VolumeInfo rhs) {
- if (VolumeInfo.ID_PRIVATE_INTERNAL.equals(lhs.getId())) {
- return -1;
- } else if (lhs.getDescription() == null) {
- return 1;
- } else if (rhs.getDescription() == null) {
- return -1;
- } else {
- return lhs.getDescription().compareTo(rhs.getDescription());
- }
- }
- };
-
private final StorageEventListener mStorageListener = new StorageEventListener() {
@Override
public void onVolumeStateChanged(VolumeInfo vol, int oldState, int newState) {
@@ -133,7 +117,7 @@
mExternalCategory.removeAll();
final List<VolumeInfo> volumes = mStorageManager.getVolumes();
- Collections.sort(volumes, sVolumeComparator);
+ Collections.sort(volumes, VolumeInfo.getDescriptionComparator());
for (VolumeInfo vol : volumes) {
if (vol.getType() == VolumeInfo.TYPE_PRIVATE) {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
new file mode 100644
index 0000000..36750c0
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
@@ -0,0 +1,68 @@
+/*
+ * 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.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.storage.VolumeInfo;
+
+import com.android.internal.util.Preconditions;
+import com.android.settings.R;
+
+public class StorageWizardMoveConfirm extends StorageWizardBase {
+ private String mPackageName;
+ private ApplicationInfo mApp;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.storage_wizard_generic);
+
+ try {
+ mPackageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ mApp = getPackageManager().getApplicationInfo(mPackageName, 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ Preconditions.checkNotNull(mVolume);
+ Preconditions.checkNotNull(mApp);
+
+ // Sanity check that target volume is candidate
+ Preconditions.checkState(
+ getPackageManager().getApplicationCandidateVolumes(mApp).contains(mVolume));
+
+ final String appName = getPackageManager().getApplicationLabel(mApp).toString();
+ final String volumeName = mStorage.getBestVolumeDescription(mVolume);
+
+ 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);
+ }
+
+ @Override
+ public void onNavigateNext() {
+ final Intent intent = new Intent(this, StorageWizardMoveProgress.class);
+ intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackageName);
+ startActivity(intent);
+ finishAffinity();
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
new file mode 100644
index 0000000..2023335
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
@@ -0,0 +1,138 @@
+/*
+ * 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 static com.android.settings.deviceinfo.StorageSettings.TAG;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageMoveObserver;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.storage.VolumeInfo;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import com.android.internal.util.Preconditions;
+import com.android.settings.R;
+
+import java.util.concurrent.CountDownLatch;
+
+public class StorageWizardMoveProgress extends StorageWizardBase {
+ private String mPackageName;
+ private ApplicationInfo mApp;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.storage_wizard_progress);
+
+ try {
+ mPackageName = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+ mApp = getPackageManager().getApplicationInfo(mPackageName, 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ Preconditions.checkNotNull(mVolume);
+ Preconditions.checkNotNull(mApp);
+
+ final String appName = getPackageManager().getApplicationLabel(mApp).toString();
+ final String volumeName = mStorage.getBestVolumeDescription(mVolume);
+
+ setHeaderText(R.string.storage_wizard_move_progress_title, appName);
+ setBodyText(R.string.storage_wizard_move_progress_body, volumeName, appName);
+
+ setCurrentProgress(20);
+
+ getNextButton().setVisibility(View.GONE);
+
+ new MoveTask().execute();
+ }
+
+ private CharSequence moveStatusToMessage(int returnCode) {
+ switch (returnCode) {
+ case PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE:
+ return getString(R.string.insufficient_storage);
+ case PackageManager.MOVE_FAILED_DOESNT_EXIST:
+ return getString(R.string.does_not_exist);
+ case PackageManager.MOVE_FAILED_FORWARD_LOCKED:
+ return getString(R.string.app_forward_locked);
+ case PackageManager.MOVE_FAILED_INVALID_LOCATION:
+ return getString(R.string.invalid_location);
+ case PackageManager.MOVE_FAILED_SYSTEM_PACKAGE:
+ return getString(R.string.system_package);
+ case PackageManager.MOVE_FAILED_INTERNAL_ERROR:
+ default:
+ return getString(R.string.insufficient_storage);
+ }
+ }
+
+ private class LocalPackageMoveObserver extends IPackageMoveObserver.Stub {
+ public int returnCode;
+ public CountDownLatch finished = new CountDownLatch(1);
+
+ @Override
+ public void packageMoved(String packageName, int returnCode) throws RemoteException {
+ this.returnCode = returnCode;
+ this.finished.countDown();
+ }
+ }
+
+ public class MoveTask extends AsyncTask<Void, Void, Integer> {
+ @Override
+ protected Integer doInBackground(Void... params) {
+ try {
+ final LocalPackageMoveObserver observer = new LocalPackageMoveObserver();
+
+ if (mApp.isExternalAsec()) {
+ getPackageManager().movePackage(mPackageName, observer,
+ PackageManager.MOVE_INTERNAL);
+ } else if (mVolume.getType() == VolumeInfo.TYPE_PUBLIC) {
+ getPackageManager().movePackage(mPackageName, observer,
+ PackageManager.MOVE_EXTERNAL_MEDIA);
+ } else {
+ getPackageManager().movePackageAndData(mPackageName, mVolume.fsUuid, observer);
+ }
+
+ observer.finished.await();
+ return observer.returnCode;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to move", e);
+ return PackageManager.MOVE_FAILED_INTERNAL_ERROR;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Integer returnCode) {
+ final Context context = StorageWizardMoveProgress.this;
+ if (returnCode == PackageManager.MOVE_SUCCEEDED) {
+ finishAffinity();
+
+ } else {
+ Log.w(TAG, "Move failed with status " + returnCode);
+ Toast.makeText(context, moveStatusToMessage(returnCode), Toast.LENGTH_LONG).show();
+ finishAffinity();
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java
index ce7ba14..581b707 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/NotificationSettings.java
@@ -128,7 +128,7 @@
final PreferenceCategory sound = (PreferenceCategory) findPreference(KEY_SOUND);
initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC,
- com.android.internal.R.drawable.ic_audio_vol_mute);
+ com.android.internal.R.drawable.ic_audio_media_mute);
initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM,
com.android.internal.R.drawable.ic_audio_alarm_mute);
if (mVoiceCapable) {
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index f2ee71d..6636b33 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -33,14 +33,14 @@
import android.service.notification.ZenModeConfig.ZenRule;
import android.text.format.DateFormat;
import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
import com.android.settings.notification.ManagedServiceSettings.Config;
import com.android.settings.notification.ZenRuleNameDialog.RuleInfo;
+import com.android.settings.widget.FloatingActionButton;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -59,7 +59,6 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- setHasOptionsMenu(true);
addPreferencesFromResource(R.xml.zen_mode_automation_settings);
mServiceListing = new ServiceListing(mContext, CONFIG);
mServiceListing.addCallback(mServiceListingCallback);
@@ -68,6 +67,21 @@
}
@Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ final FloatingActionButton fab = getFloatingActionButton();
+ fab.setVisibility(View.VISIBLE);
+ fab.setImageResource(R.drawable.ic_menu_add_white);
+ fab.setContentDescription(getString(R.string.zen_mode_time_add_rule));
+ fab.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showAddRuleDialog();
+ }
+ });
+ }
+
+ @Override
public void onDestroy() {
super.onDestroy();
mServiceListing.setListening(false);
@@ -75,20 +89,6 @@
}
@Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- inflater.inflate(R.menu.zen_mode_automation, menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == R.id.add) {
- showAddRuleDialog();
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
protected void onZenModeChanged() {
// don't care
}
diff --git a/src/com/android/settings/notification/ZenModeVoiceActivity.java b/src/com/android/settings/notification/ZenModeVoiceActivity.java
index c7c1151..2994ed1 100644
--- a/src/com/android/settings/notification/ZenModeVoiceActivity.java
+++ b/src/com/android/settings/notification/ZenModeVoiceActivity.java
@@ -65,22 +65,24 @@
boolean enabled = intent.getBooleanExtra(EXTRA_DO_NOT_DISTURB_MODE_ENABLED, false);
boolean specified = intent.hasExtra(EXTRA_DO_NOT_DISTURB_MODE_ENABLED);
+ setHeader(getString(R.string.zen_mode_interruptions_voice_header));
+
List<VoiceSelection> states = new ArrayList<VoiceSelection>();
if (!specified || enabled) {
states.add(new ModeSelection(this, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
- R.string.zen_mode_option_important_interruptions,
- R.string.zen_mode_option_important_voice_synonyms));
+ R.string.zen_mode_option_voice_important_interruptions,
+ R.string.zen_mode_option_voice_important_synonyms));
states.add(new ModeSelection(this, Global.ZEN_MODE_ALARMS,
- R.string.zen_mode_option_alarms,
- R.string.zen_mode_option_alarms_voice_synonyms));
+ R.string.zen_mode_option_voice_alarms,
+ R.string.zen_mode_option_voice_alarms_synonyms));
states.add(new ModeSelection(this, Global.ZEN_MODE_NO_INTERRUPTIONS,
- R.string.zen_mode_option_no_interruptions,
- R.string.zen_mode_option_no_interruptions_voice_synonyms));
+ R.string.zen_mode_option_voice_no_interruptions,
+ R.string.zen_mode_option_voice_no_interruptions_synonyms));
}
if (!specified || !enabled) {
states.add(new ModeSelection(this, Global.ZEN_MODE_OFF,
- R.string.zen_mode_option_off,
- R.string.zen_mode_option_off_voice_synonyms));
+ R.string.zen_mode_option_voice_all_interruptions,
+ R.string.zen_mode_option_voice_all_interruptions_synonyms));
}
VoiceSelectionFragment fragment = new VoiceSelectionFragment();
fragment.setArguments(VoiceSelectionFragment.createArguments(
@@ -98,8 +100,10 @@
pickDuration(selection.getLabel(), mode);
return;
}
+ setZenModeConfig(mode, conditionSelection.mCondition);
+ } else {
+ setZenModeConfig(Global.ZEN_MODE_OFF, null);
}
- setZenModeConfig(mode, conditionSelection.mCondition);
notifySuccess(getChangeSummary(mode, conditionSelection));
finish();
}
@@ -112,6 +116,8 @@
*/
private void pickDuration(CharSequence label, final int mode) {
setTitle(label.toString());
+ setHeader(null);
+
List<VoiceSelection> states = new ArrayList<VoiceSelection>();
states.add(new ConditionSelection(null, -1,
getString(R.string.zen_mode_duration_indefinte_voice_label),
@@ -137,13 +143,6 @@
showFragment(fragment, "pick_duration_fragment");
}
- private void showFragment(Fragment fragment, String tag) {
- getFragmentManager()
- .beginTransaction()
- .replace(R.id.fragment_root, fragment, tag)
- .commit();
- }
-
private void setZenModeConfig(int mode, Condition condition) {
if (condition != null) {
NotificationManager.from(this).setZenMode(mode, condition.id, TAG);
diff --git a/src/com/android/settings/utils/VoiceSelectionFragment.java b/src/com/android/settings/utils/VoiceSelectionFragment.java
index c2e80d3..1e4e7e4 100644
--- a/src/com/android/settings/utils/VoiceSelectionFragment.java
+++ b/src/com/android/settings/utils/VoiceSelectionFragment.java
@@ -111,7 +111,7 @@
}
if (mOnItemSelectedListener != null) {
- mOnItemSelectedListener.onItemSelected(position, getSelectionAt(position));
+ mOnItemSelectedListener.onItemSelected(position, getSelectionAt(position));
}
}
diff --git a/src/com/android/settings/utils/VoiceSettingsActivity.java b/src/com/android/settings/utils/VoiceSettingsActivity.java
index ac5b8be..21849a4 100644
--- a/src/com/android/settings/utils/VoiceSettingsActivity.java
+++ b/src/com/android/settings/utils/VoiceSettingsActivity.java
@@ -16,11 +16,16 @@
package com.android.settings.utils;
+import com.android.settings.R;
+
import android.app.Activity;
+import android.app.Fragment;
import android.app.VoiceInteractor;
import android.app.VoiceInteractor.CompleteVoiceRequest;
import android.content.Intent;
import android.os.Bundle;
+import android.view.View;
+import android.widget.TextView;
import android.util.Log;
/**
@@ -65,10 +70,30 @@
}
}
+ protected void setHeader(String label) {
+ TextView header = (TextView) findViewById(R.id.voice_fragment_header);
+ if (header != null) {
+ if (label != null) {
+ header.setText(label);
+ header.setVisibility(View.VISIBLE);
+ } else {
+ header.setVisibility(View.GONE);
+ }
+ }
+ }
+
/**
* Indicates when the setting could not be changed.
*/
protected void notifyFailure(String reason) {
getVoiceInteractor().submitRequest(new VoiceInteractor.AbortVoiceRequest(reason, null));
}
+
+ protected void showFragment(Fragment fragment, String tag) {
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.voice_fragment_root, fragment, tag)
+ .commit();
+ }
+
}
diff --git a/src/com/android/settings/widget/FloatingActionButton.java b/src/com/android/settings/widget/FloatingActionButton.java
new file mode 100644
index 0000000..181c6c0
--- /dev/null
+++ b/src/com/android/settings/widget/FloatingActionButton.java
@@ -0,0 +1,49 @@
+/*
+ * 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.widget;
+
+import android.animation.AnimatorInflater;
+import android.content.Context;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.widget.ImageView;
+
+import com.android.settings.R;
+
+public class FloatingActionButton extends ImageView {
+
+ public FloatingActionButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setScaleType(ScaleType.CENTER);
+ setStateListAnimator(AnimatorInflater.loadStateListAnimator(context, R.anim.fab_elevation));
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setOval(0, 0, getWidth(), getHeight());
+ }
+ });
+ setClipToOutline(true);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ invalidateOutline();
+ }
+}
diff --git a/src/com/android/settings/wifi/AccessPointPreference.java b/src/com/android/settings/wifi/AccessPointPreference.java
index f68410a..8a24bc9 100644
--- a/src/com/android/settings/wifi/AccessPointPreference.java
+++ b/src/com/android/settings/wifi/AccessPointPreference.java
@@ -15,16 +15,9 @@
*/
package com.android.settings.wifi;
-import android.app.AppGlobals;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
-import android.net.wifi.WifiConfiguration;
-import android.os.RemoteException;
-import android.os.UserHandle;
import android.preference.Preference;
import android.view.View;
import android.widget.TextView;
@@ -67,36 +60,6 @@
notifyChanged();
}
- public void showAppIcon() {
- PackageManager pm = getContext().getPackageManager();
- String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID);
- WifiConfiguration mConfig = mAccessPoint.getConfig();
-
- Drawable drawable = pm.getDefaultActivityIcon();
- if (mConfig == null) {
- drawable.setAlpha(0);
- } else {
- int userId = UserHandle.getUserId(mConfig.creatorUid);
- ApplicationInfo appInfo = null;
- if (mConfig.creatorName.equals(systemName)) {
- appInfo = getContext().getApplicationInfo();
- } else {
- try {
- IPackageManager ipm = AppGlobals.getPackageManager();
- appInfo = ipm.getApplicationInfo(mConfig.creatorName, 0 /* flags */, userId);
- } catch (RemoteException rex) {
- // use default app icon
- }
- }
- if (appInfo != null) {
- drawable = appInfo.loadIcon(pm);
- drawable = pm.getUserBadgedIcon(drawable, new UserHandle(userId));
- }
- }
-
- setIcon(drawable);
- }
-
protected void updateIcon(int level, Context context) {
if (level == -1) {
setIcon(null);
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index 2627bc4..6726717 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -16,12 +16,19 @@
package com.android.settings.wifi;
+import android.app.AppGlobals;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.util.Log;
@@ -93,11 +100,32 @@
preferenceScreen.removeAll();
+ PackageManager pm = context.getPackageManager();
+ String systemName = pm.getNameForUid(android.os.Process.SYSTEM_UID);
+
final int accessPointsSize = accessPoints.size();
for (int i = 0; i < accessPointsSize; ++i){
AccessPointPreference preference = new AccessPointPreference(accessPoints.get(i),
context);
- preference.setShowSummary(false);
+ WifiConfiguration config = accessPoints.get(i).getConfig();
+ if (config != null) {
+ int userId = UserHandle.getUserId(config.creatorUid);
+ ApplicationInfo appInfo = null;
+ if (config.creatorName != null && config.creatorName.equals(systemName)) {
+ appInfo = context.getApplicationInfo();
+ } else {
+ try {
+ IPackageManager ipm = AppGlobals.getPackageManager();
+ appInfo = ipm.getApplicationInfo(config.creatorName, 0 /* flags */, userId);
+ } catch (RemoteException rex) {
+ }
+ }
+ if (appInfo != null) {
+ preference.setSummary(getResources().getString(appInfo.labelRes));
+ }
+ } else {
+ preference.setShowSummary(false);
+ }
preferenceScreen.addPreference(preference);
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index cb6be53..f46edac 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -93,7 +93,6 @@
private static final int MENU_ID_FORGET = Menu.FIRST + 7;
private static final int MENU_ID_MODIFY = Menu.FIRST + 8;
private static final int MENU_ID_WRITE_NFC = Menu.FIRST + 9;
- private static final int MENU_ID_APPS = Menu.FIRST + 10;
public static final int WIFI_DIALOG_ID = 1;
/* package */ static final int WPS_PBC_DIALOG_ID = 2;
@@ -120,9 +119,6 @@
private TextView mEmptyView;
- private boolean showAppIcons = false;
- private MenuItem showAppMenuItem = null;
-
// this boolean extra specifies whether to disable the Next button when not connected. Used by
// account creation outside of setup wizard.
private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect";
@@ -324,8 +320,6 @@
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- showAppMenuItem = menu.add(Menu.NONE, MENU_ID_APPS, 0, R.string.wifi_menu_apps);
- showAppMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
ta.recycle();
}
@@ -406,16 +400,6 @@
null);
}
return true;
- case MENU_ID_APPS:
- showAppIcons = !showAppIcons;
-
- if (showAppIcons) {
- showAppMenuItem.setTitle(R.string.wifi_menu_apps_strength);
- } else {
- showAppMenuItem.setTitle(R.string.wifi_menu_apps);
- }
- onAccessPointsChanged();
- return true;
}
return super.onOptionsItemSelected(item);
}
@@ -584,9 +568,6 @@
if (accessPoint.getLevel() != -1) {
AccessPointPreference preference = new AccessPointPreference(accessPoint,
getActivity());
- if (showAppIcons) {
- preference.showAppIcon();
- }
getPreferenceScreen().addPreference(preference);
accessPoint.setListener(this);
diff --git a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
index 5716bec..9862258 100644
--- a/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
+++ b/src/com/android/settings/wifi/WifiSettingsForSetupWizard.java
@@ -16,6 +16,7 @@
package com.android.settings.wifi;
+import android.app.Dialog;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
import android.os.Bundle;
@@ -29,6 +30,7 @@
import android.widget.TextView;
import com.android.settings.R;
+import com.android.settings.SetupWizardUtils;
/**
* This customized version of WifiSettings is shown to the user only during Setup Wizard. Menu
@@ -119,6 +121,13 @@
}
@Override
+ public Dialog onCreateDialog(int dialogId) {
+ final Dialog dialog = super.onCreateDialog(dialogId);
+ SetupWizardUtils.applyImmersiveFlags(dialog);
+ return dialog;
+ }
+
+ @Override
protected void connect(final WifiConfiguration config) {
WifiSetupActivity activity = (WifiSetupActivity) getActivity();
activity.networkSelected();
diff --git a/src/com/android/settings/wifi/WifiSetupActivity.java b/src/com/android/settings/wifi/WifiSetupActivity.java
index 155fd93..d9974b4 100644
--- a/src/com/android/settings/wifi/WifiSetupActivity.java
+++ b/src/com/android/settings/wifi/WifiSetupActivity.java
@@ -263,24 +263,26 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int messageRes = getArguments().getInt("messageRes");
- return new AlertDialog.Builder(getActivity())
+ final AlertDialog dialog = new AlertDialog.Builder(getActivity())
.setMessage(messageRes)
.setCancelable(false)
.setPositiveButton(R.string.wifi_skip_anyway,
new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- WifiSetupActivity activity = (WifiSetupActivity) getActivity();
- activity.finishOrNext(RESULT_SKIP);
- }
- })
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ WifiSetupActivity activity = (WifiSetupActivity) getActivity();
+ activity.finishOrNext(RESULT_SKIP);
+ }
+ })
.setNegativeButton(R.string.wifi_dont_skip,
new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- }
- })
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ }
+ })
.create();
+ SetupWizardUtils.applyImmersiveFlags(dialog);
+ return dialog;
}
}
}