Merge "Update battery settings strings" into pi-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 14fe92b..8767198 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -207,6 +207,8 @@
                 android:value="com.android.settings.category.ia.homepage"/>
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
+            <meta-data android:name="android.metadata.SLICE_URI"
+                android:value="content://android.settings.slices/action/toggle_bluetooth_switch" />
         </activity>
 
         <activity android:name="AirplaneModeVoiceActivity"
@@ -2235,6 +2237,8 @@
                 android:value="com.android.settings.category.ia.homepage" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                 android:value="com.android.settings.fuelgauge.PowerUsageSummary" />
+            <meta-data android:name="android.metadata.SLICE_URI"
+                android:value="content://android.settings.slices/action/auto_brightness" />
         </activity>
 
         <activity
@@ -2251,6 +2255,8 @@
                 android:value="com.android.settings.fuelgauge.batterysaver.BatterySaverSettings" />
             <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
                 android:value="true" />
+            <meta-data android:name="android.metadata.SLICE_URI"
+                android:value="content://android.settings.slices/action/battery_saver_summary" />
         </activity>
 
         <activity android:name=".fuelgauge.BatterySaverModeVoiceActivity"
@@ -2670,6 +2676,8 @@
                 android:value="true" />
             <meta-data android:name="com.android.settings.summary"
                 android:resource="@string/sound_dashboard_summary"/>
+            <meta-data android:name="android.metadata.SLICE_URI"
+                android:value="content://android.settings.slices/action/alarm_volume" />
         </activity>
 
         <!-- Show apps for which application-level notification settings are applicable -->
diff --git a/res/drawable-nodpi/gesture_swipe_up.png b/res/drawable-nodpi/gesture_swipe_up.png
new file mode 100644
index 0000000..b9390d2
--- /dev/null
+++ b/res/drawable-nodpi/gesture_swipe_up.png
Binary files differ
diff --git a/res/layout-land/choose_lock_pattern.xml b/res/layout-land/choose_lock_pattern.xml
index cba6173..4d6f798 100644
--- a/res/layout-land/choose_lock_pattern.xml
+++ b/res/layout-land/choose_lock_pattern.xml
@@ -120,6 +120,14 @@
                     android:clipToPadding="false"
                     android:orientation="horizontal">
 
+                    <!-- left : skip -->
+                    <Button android:id="@+id/skip_button"
+                        style="@style/SuwGlifButton.Secondary"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/skip_label"
+                        android:visibility="gone" />
+
                     <!-- left / top button: skip, or re-try -->
                     <Button android:id="@+id/footerLeftButton"
                         style="@style/SetupWizardButton.Negative"
diff --git a/res/layout/choose_lock_pattern_common_footer.xml b/res/layout/choose_lock_pattern_common_footer.xml
index fc36624..deea8f0 100644
--- a/res/layout/choose_lock_pattern_common_footer.xml
+++ b/res/layout/choose_lock_pattern_common_footer.xml
@@ -16,9 +16,9 @@
 -->
 
 <!-- TODO: Use aapt:attr when it is fixed (b/36809755) -->
-<LinearLayout
+<com.android.setupwizardlib.view.ButtonBarLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    style="@style/SuwGlifButtonBar"
+    style="@style/SuwGlifButtonBar.Stackable"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
@@ -49,4 +49,4 @@
         android:layout_height="wrap_content"
         android:text="@string/lockpattern_tutorial_continue_label" />
 
-</LinearLayout>
+</com.android.setupwizardlib.view.ButtonBarLayout>
diff --git a/res/raw/gesture_swipe_up.mp4 b/res/raw/gesture_swipe_up.mp4
new file mode 100644
index 0000000..16cbb2b
--- /dev/null
+++ b/res/raw/gesture_swipe_up.mp4
Binary files differ
diff --git a/res/xml/swipe_up_gesture_settings.xml b/res/xml/swipe_up_gesture_settings.xml
index 9c9ae7b..0f1dc4a 100644
--- a/res/xml/swipe_up_gesture_settings.xml
+++ b/res/xml/swipe_up_gesture_settings.xml
@@ -21,6 +21,11 @@
     android:key="gesture_swipe_up_screen"
     android:title="@string/swipe_up_to_switch_apps_title">
 
+    <com.android.settings.widget.VideoPreference
+        android:key="gesture_swipe_up_video"
+        app:animation="@raw/gesture_swipe_up"
+        app:preview="@drawable/gesture_swipe_up" />
+
     <SwitchPreference
         android:key="gesture_swipe_up"
         android:title="@string/swipe_up_to_switch_apps_title"
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index 24ed0b9..385e8ff 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -23,10 +23,9 @@
     settings:keywords="@string/keywords_zen_mode_settings">
 
     <!-- sound vibration -->
-    <CheckBoxPreference
+    <com.android.settings.widget.DisabledCheckBoxPreference
         android:key="zen_effect_sound"
-        android:title="@string/zen_mode_block_effect_sound"
-        android:enabled="false" />
+        android:title="@string/zen_mode_block_effect_sound" />
 
     <!-- What to block (effects) -->
     <Preference
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index ab8cc71..301e71b 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -176,7 +176,8 @@
     private static final int NO_USER_SPECIFIED = -1;
 
     // sort order
-    private int mSortOrder = R.id.sort_order_alpha;
+    @VisibleForTesting
+    int mSortOrder = R.id.sort_order_alpha;
 
     // whether showing system apps.
     private boolean mShowSystem;
@@ -649,9 +650,8 @@
         switch (item.getItemId()) {
             case R.id.sort_order_alpha:
             case R.id.sort_order_size:
-                mSortOrder = menuId;
                 if (mApplications != null) {
-                    mApplications.rebuild(mSortOrder);
+                    mApplications.rebuild(menuId);
                 }
                 break;
             case R.id.show_system:
@@ -712,6 +712,7 @@
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
         mFilter = mFilterAdapter.getFilter(position);
         mApplications.setFilter(mFilter);
+
         if (DEBUG) Log.d(TAG, "Selecting filter " + mFilter);
     }
 
@@ -986,6 +987,7 @@
             if (sort == mLastSortMode) {
                 return;
             }
+            mManageApplications.mSortOrder = sort;
             mLastSortMode = sort;
             rebuild();
         }
diff --git a/src/com/android/settings/gestures/SwipeUpPreferenceController.java b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
index eb74e07..a20cd97 100644
--- a/src/com/android/settings/gestures/SwipeUpPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
@@ -33,8 +33,7 @@
     private final int ON = 1;
     private final int OFF = 0;
 
-    // TODO(77474484): Update when swipe up illustration video is ready
-    private static final String PREF_KEY_VIDEO = "";
+    private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
     private final UserManager mUserManager;
 
     public SwipeUpPreferenceController(Context context, String key) {
diff --git a/src/com/android/settings/search/DeviceIndexFeatureProvider.java b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
index 690943e..2273ffd 100644
--- a/src/com/android/settings/search/DeviceIndexFeatureProvider.java
+++ b/src/com/android/settings/search/DeviceIndexFeatureProvider.java
@@ -33,6 +33,10 @@
     // TODO: Remove this and index all action and intent slices through search index.
     String[] ACTIONS_TO_INDEX = new String[]{
             Settings.ACTION_WIFI_SETTINGS,
+            Settings.ACTION_BATTERY_SAVER_SETTINGS,
+            Settings.ACTION_BLUETOOTH_SETTINGS,
+            "android.intent.action.POWER_USAGE_SUMMARY",
+            Settings.ACTION_SOUND_SETTINGS,
     };
 
     String TAG = "DeviceIndex";
@@ -40,7 +44,7 @@
     String INDEX_VERSION = "settings:index_version";
 
     // Increment when new items are added to ensure they get pushed to the device index.
-    int VERSION = 1;
+    int VERSION = 2;
 
     boolean isIndexingEnabled();
 
diff --git a/src/com/android/settings/widget/DisabledCheckBoxPreference.java b/src/com/android/settings/widget/DisabledCheckBoxPreference.java
new file mode 100644
index 0000000..482cff3
--- /dev/null
+++ b/src/com/android/settings/widget/DisabledCheckBoxPreference.java
@@ -0,0 +1,62 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.PreferenceViewHolder;
+
+/**
+ * A CheckboxPreference with a disabled checkbox. Differs from CheckboxPreference.setDisabled()
+ * in that the text is not dimmed.
+ */
+public class DisabledCheckBoxPreference extends CheckBoxPreference {
+
+    public DisabledCheckBoxPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public DisabledCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public DisabledCheckBoxPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public DisabledCheckBoxPreference(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+
+        View view = holder.findViewById(android.R.id.checkbox);
+        view.setEnabled(false);
+        holder.itemView.setEnabled(false);
+    }
+
+    @Override
+    protected void performClick(View view) {
+        // Do nothing
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index c751462..66fa212 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -23,6 +23,8 @@
 import static com.android.settings.applications.manageapplications.ManageApplications.LIST_TYPE_NOTIFICATION;
 import static com.google.common.truth.Truth.assertThat;
 
+import static junit.framework.Assert.assertEquals;
+
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
@@ -303,6 +305,23 @@
         verify(holder, never()).updateSwitch(any(), anyBoolean(), anyBoolean());
     }
 
+    @Test
+    public void sortOrderSavedOnRebuild() {
+        ManageApplications manageApplications = mock(ManageApplications.class);
+        manageApplications.mListType = LIST_TYPE_NOTIFICATION;
+        manageApplications.mSortOrder = -1;
+        ManageApplications.ApplicationsAdapter adapter =
+                new ManageApplications.ApplicationsAdapter(mState,
+                        manageApplications, mock(AppFilterItem.class),
+                        mock(Bundle.class));
+
+        adapter.rebuild(mSortRecent.getItemId());
+        assertThat(manageApplications.mSortOrder).isEqualTo(mSortRecent.getItemId());
+
+        adapter.rebuild(mSortFrequent.getItemId());
+        assertThat(manageApplications.mSortOrder).isEqualTo(mSortFrequent.getItemId());
+    }
+
     private void setUpOptionMenus() {
         when(mMenu.findItem(anyInt())).thenAnswer(invocation -> {
             final Object[] args = invocation.getArguments();
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index 63bf711..e38cc6a 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -101,9 +101,7 @@
         ReflectionHelpers.callInstanceMethod(lockPatternView, "notifyPatternDetected");
     }
 
-    @Config(qualifiers = "sw400dp")
-    @Test
-    public void sw400dp_shouldShowScreenLockOptions() {
+    private void verifyScreenLockOptionsShown() {
         Button button = mActivity.findViewById(R.id.screen_lock_options);
         assertThat(button).isNotNull();
         assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
@@ -115,14 +113,36 @@
         assertThat(count).named("List items shown").isEqualTo(3);
     }
 
-    @Config(qualifiers = "sw300dp")
+    @Config(qualifiers = "sw400dp")
     @Test
-    public void smallScreens_shouldHideScreenLockOptions() {
+    public void sw400dp_shouldShowScreenLockOptions() {
+        verifyScreenLockOptionsShown();
+    }
+
+    @Config(qualifiers = "sw400dp-land")
+    @Test
+    public void sw400dpLandscape_shouldShowScreenLockOptions() {
+        verifyScreenLockOptionsShown();
+    }
+
+    private void verifyScreenLockOptionsHidden() {
         Button button = mActivity.findViewById(R.id.screen_lock_options);
         assertThat(button).isNotNull();
         assertThat(button.getVisibility()).isEqualTo(View.GONE);
     }
 
+    @Config(qualifiers = "sw300dp")
+    @Test
+    public void smallScreens_shouldHideScreenLockOptions() {
+        verifyScreenLockOptionsHidden();
+    }
+
+    @Config(qualifiers = "sw300dp-land")
+    @Test
+    public void smallScreensLandscape_shouldHideScreenLockOptions() {
+        verifyScreenLockOptionsHidden();
+    }
+
     @Test
     public void skipButton_shouldBeVisible_duringNonFingerprintFlow() {
         Button skipButton = mActivity.findViewById(R.id.skip_button);
diff --git a/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java
new file mode 100644
index 0000000..5ab7013
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import android.support.v7.preference.R;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.widget.LinearLayout;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class DisabledCheckBoxPreferenceTest {
+
+    private Context mContext;
+    private View mRootView;
+    private DisabledCheckBoxPreference mPref;
+    private PreferenceViewHolder mHolder;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mRootView = View.inflate(mContext, R.layout.preference, null /* parent */);
+        mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+        mPref = new DisabledCheckBoxPreference(mContext);
+    }
+
+    private void inflatePreference() {
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        final LinearLayout widgetView = mHolder.itemView.findViewById(android.R.id.widget_frame);
+        assertThat(widgetView).isNotNull();
+        inflater.inflate(R.layout.preference_widget_checkbox, widgetView, true);
+        mPref.onBindViewHolder(mHolder);
+    }
+
+    @Test
+    public void onBindViewHolder_checkboxDisabled() {
+        inflatePreference();
+        assertThat(mRootView.findViewById(android.R.id.checkbox).isEnabled()).isFalse();
+    }
+
+    @Test
+    public void checkboxOnClick_doesNothing() {
+        Preference.OnPreferenceClickListener onClick =
+                mock(Preference.OnPreferenceClickListener.class);
+        mPref.setOnPreferenceClickListener(onClick);
+        inflatePreference();
+
+        mPref.performClick(mRootView);
+
+        verify(onClick, never()).onPreferenceClick(any());
+    }
+}
diff --git a/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java b/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java
new file mode 100644
index 0000000..b3842d2
--- /dev/null
+++ b/tests/unit/src/com/android/settings/fuelgauge/batterytip/RestrictAppTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.fuelgauge.batterytip;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class RestrictAppTest {
+    private static final String BATTERY_INTENT = "android.intent.action.POWER_USAGE_SUMMARY";
+    private static final String PACKAGE_SETTINGS = "com.android.settings";
+    private static final String PACKAGE_SYSTEM_UI = "com.android.systemui";
+
+    private BatteryDatabaseManager mBatteryDatabaseManager;
+    private PackageManager mPackageManager;
+
+    @Before
+    public void setUp() {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        mPackageManager = context.getPackageManager();
+        mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
+        mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(System.currentTimeMillis() +
+                TimeUnit.DAYS.toMillis(1));
+    }
+
+    @Test
+    public void testBatterySettings_hasOneAnomaly_showAnomaly() throws
+            PackageManager.NameNotFoundException {
+        mBatteryDatabaseManager.insertAnomaly(mPackageManager.getPackageUid(PACKAGE_SETTINGS, 0),
+                PACKAGE_SETTINGS, 1,
+                AnomalyDatabaseHelper.State.NEW, System.currentTimeMillis());
+
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
+        onView(withText("Restrict 1 app")).check(matches(isDisplayed()));
+    }
+
+    @Test
+    public void testBatterySettings_hasTwoAnomalies_showAnomalies() throws
+            PackageManager.NameNotFoundException {
+        mBatteryDatabaseManager.insertAnomaly(mPackageManager.getPackageUid(PACKAGE_SETTINGS, 0),
+                PACKAGE_SETTINGS, 1,
+                AnomalyDatabaseHelper.State.NEW, System.currentTimeMillis());
+        mBatteryDatabaseManager.insertAnomaly(mPackageManager.getPackageUid(PACKAGE_SYSTEM_UI, 0),
+                PACKAGE_SYSTEM_UI, 1,
+                AnomalyDatabaseHelper.State.NEW, System.currentTimeMillis());
+
+        Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+        instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
+        onView(withText("Restrict 2 apps")).check(matches(isDisplayed()));
+    }
+}