Merge "Index input & gesture settings page."
diff --git a/res/drawable/wifi_friction.xml b/res/drawable/wifi_friction.xml
index cd13dac..c46f5b4 100644
--- a/res/drawable/wifi_friction.xml
+++ b/res/drawable/wifi_friction.xml
@@ -16,9 +16,10 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
-    <item settings:state_encrypted="true"
-          settings:state_saved="true"
-          android:drawable="@drawable/ic_friction_lock_open"/>
+    <item
+        settings:state_encrypted="true"
+        settings:state_saved="true"
+        android:drawable="@drawable/ic_friction_lock_closed"/>
     <item
         settings:state_encrypted="true"
         settings:state_saved="false"
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index c4b97d4..3d49719 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -319,7 +319,7 @@
             final int numSippers = usageList.size();
             for (int i = 0; i < numSippers; i++) {
                 final BatterySipper sipper = usageList.get(i);
-                if ((sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP) {
+                if (shouldHideSipper(sipper)) {
                     continue;
                 }
                 double totalPower = USE_FAKE_DATA ? 4000 : mStatsHelper.getTotalPower();
@@ -375,7 +375,7 @@
                 pref.setTitle(entry.getLabel());
                 pref.setOrder(i + 1);
                 pref.setPercent(percentOfMax, percentOfTotal);
-                if ((sipper.drainType != DrainType.APP || sipper.uidObj.getUid() == 0)
+                if ((sipper.drainType != DrainType.APP || sipper.uidObj.getUid() == Process.ROOT_UID)
                          && sipper.drainType != DrainType.USER) {
                     pref.setTint(colorControl);
                 }
@@ -396,6 +396,16 @@
     }
 
     @VisibleForTesting
+    boolean shouldHideSipper(BatterySipper sipper) {
+        final DrainType drainType = sipper.drainType;
+        final int uid = sipper.getUid();
+
+        return drainType == DrainType.IDLE || drainType == DrainType.CELL
+                || uid == Process.ROOT_UID || uid == Process.SYSTEM_UID
+                || (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP;
+    }
+
+    @VisibleForTesting
     String extractKeyFromSipper(BatterySipper sipper) {
         if (sipper.uidObj != null) {
             return Integer.toString(sipper.getUid());
diff --git a/src/com/android/settings/notification/WorkSoundPreferenceController.java b/src/com/android/settings/notification/WorkSoundPreferenceController.java
index cc671ad..96d88c9 100644
--- a/src/com/android/settings/notification/WorkSoundPreferenceController.java
+++ b/src/com/android/settings/notification/WorkSoundPreferenceController.java
@@ -20,8 +20,11 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.FragmentManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.media.AudioSystem;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -46,11 +49,11 @@
 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
 import com.android.settings.core.lifecycle.Lifecycle;
 import com.android.settings.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.lifecycle.events.OnPause;
 import com.android.settings.core.lifecycle.events.OnResume;
 
-
 public class WorkSoundPreferenceController extends PreferenceController implements
-    OnPreferenceChangeListener, LifecycleObserver, OnResume {
+    OnPreferenceChangeListener, LifecycleObserver, OnResume, OnPause {
 
     private static final String TAG = "WorkSoundPrefController";
     private static final String KEY_WORK_CATEGORY = "sound_work_settings_section";
@@ -97,18 +100,18 @@
 
     @Override
     public void onResume() {
-        if (isAvailable()) {
-            if ((mWorkPreferenceCategory == null)) {
-                // Work preferences not yet set
-                mParent.addPreferencesFromResource(R.xml.sound_work_settings);
-                initWorkPreferences();
-            }
-            if (!mWorkUsePersonalSounds.isChecked()) {
-                updateWorkRingtoneSummaries();
-            }
-        } else {
-            maybeRemoveWorkPreferences();
-        }
+        IntentFilter managedProfileFilter = new IntentFilter();
+        managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
+        managedProfileFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
+        mContext.registerReceiver(mManagedProfileReceiver, managedProfileFilter);
+
+        mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
+        initWorkPreferences();
+    }
+
+    @Override
+    public void onPause() {
+        mContext.unregisterReceiver(mManagedProfileReceiver);
     }
 
     @Override
@@ -118,8 +121,8 @@
 
     @Override
     public boolean isAvailable() {
-        mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
-        return mManagedProfileId != UserHandle.USER_NULL && shouldShowRingtoneSettings();
+        return mHelper.getManagedProfileId(mUserManager) != UserHandle.USER_NULL
+                && shouldShowRingtoneSettings();
     }
 
     @Override
@@ -184,17 +187,37 @@
     }
 
     private void initWorkPreferences() {
-        mWorkPreferenceCategory = (PreferenceGroup) mParent.getPreferenceScreen()
-            .findPreference(KEY_WORK_CATEGORY);
-        mWorkUsePersonalSounds = (TwoStatePreference) mParent.getPreferenceScreen()
-            .findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
-        mWorkPhoneRingtonePreference = initWorkPreference(KEY_WORK_PHONE_RINGTONE);
-        mWorkNotificationRingtonePreference = initWorkPreference(KEY_WORK_NOTIFICATION_RINGTONE);
-        mWorkAlarmRingtonePreference = initWorkPreference(KEY_WORK_ALARM_RINGTONE);
+        if (mManagedProfileId == UserHandle.USER_NULL || !isAvailable()) {
+            maybeRemoveWorkPreferences();
+            return;
+        }
 
-        if (!mVoiceCapable) {
-            mWorkPreferenceCategory.removePreference(mWorkPhoneRingtonePreference);
-            mWorkPhoneRingtonePreference = null;
+        if (mWorkPreferenceCategory == null) {
+            mParent.addPreferencesFromResource(R.xml.sound_work_settings);
+            final PreferenceScreen screen = mParent.getPreferenceScreen();
+
+            mWorkPreferenceCategory = (PreferenceGroup) screen.findPreference(KEY_WORK_CATEGORY);
+            mWorkUsePersonalSounds = (TwoStatePreference)
+                    screen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS);
+            mWorkPhoneRingtonePreference = initWorkPreference(KEY_WORK_PHONE_RINGTONE);
+            mWorkNotificationRingtonePreference = initWorkPreference(
+                    KEY_WORK_NOTIFICATION_RINGTONE);
+            mWorkAlarmRingtonePreference = initWorkPreference(KEY_WORK_ALARM_RINGTONE);
+
+            mWorkUsePersonalSounds.setOnPreferenceChangeListener((Preference p, Object value) -> {
+                if ((boolean) value) {
+                    UnifyWorkDialogFragment.show(mParent);
+                    return false;
+                } else {
+                    disableWorkSync();
+                    return true;
+                }
+            });
+
+            if (!mVoiceCapable) {
+                mWorkPreferenceCategory.removePreference(mWorkPhoneRingtonePreference);
+                mWorkPhoneRingtonePreference = null;
+            }
         }
 
         Context managedProfileContext = getManagedProfileContext();
@@ -204,19 +227,6 @@
         } else {
             disableWorkSyncSettings();
         }
-
-        mWorkUsePersonalSounds.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
-            @Override
-            public boolean onPreferenceChange(Preference preference, Object newValue) {
-                if ((boolean) newValue) {
-                    UnifyWorkDialogFragment.show(mParent);
-                    return false;
-                } else {
-                    disableWorkSync();
-                    return true;
-                }
-            }
-        });
     }
 
     void enableWorkSync() {
@@ -267,7 +277,6 @@
 
     private void maybeRemoveWorkPreferences() {
         if (mWorkPreferenceCategory == null) {
-            // No work preferences to remove
             return;
         }
         mParent.getPreferenceScreen().removePreference(mWorkPreferenceCategory);
@@ -277,6 +286,37 @@
         mWorkAlarmRingtonePreference = null;
     }
 
+    public void onManagedProfileAdded(@UserIdInt int profileId) {
+        if (mManagedProfileId == UserHandle.USER_NULL) {
+            mManagedProfileId = profileId;
+            initWorkPreferences();
+        }
+    }
+
+    public void onManagedProfileRemoved(@UserIdInt int profileId) {
+        if (mManagedProfileId == profileId) {
+            mManagedProfileId = mHelper.getManagedProfileId(mUserManager);
+            initWorkPreferences();
+        }
+    }
+
+    private final BroadcastReceiver mManagedProfileReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final int userId = ((UserHandle) intent.getExtra(Intent.EXTRA_USER)).getIdentifier();
+            switch (intent.getAction()) {
+                case Intent.ACTION_MANAGED_PROFILE_ADDED: {
+                    onManagedProfileAdded(userId);
+                    return;
+                }
+                case Intent.ACTION_MANAGED_PROFILE_REMOVED: {
+                    onManagedProfileRemoved(userId);
+                    return;
+                }
+            }
+        }
+    };
+
     public static class UnifyWorkDialogFragment extends InstrumentedDialogFragment
         implements DialogInterface.OnClickListener {
         private static final String TAG = "UnifyWorkDialogFragment";
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 1cf83f1..35df218 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.os.Process;
 import android.text.TextUtils;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -28,7 +29,6 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import org.junit.Before;
 import org.junit.Test;
-
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
 import org.mockito.Mock;
@@ -52,6 +52,7 @@
 public class PowerUsageSummaryTest {
     private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
     private static final int UID = 123;
+    private static final int POWER_MAH = 100;
 
     private static final Intent ADDITIONAL_BATTERY_INFO_INTENT =
             new Intent("com.example.app.ADDITIONAL_BATTERY_INFO");
@@ -96,6 +97,7 @@
 
         when(mBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
         when(mBatterySipper.getUid()).thenReturn(UID);
+        mBatterySipper.totalPowerMah = POWER_MAH;
     }
 
     @Test
@@ -152,6 +154,39 @@
         assertThat(key).isEqualTo(Integer.toString(mBatterySipper.getUid()));
     }
 
+    @Test
+    public void testShouldHideSipper_TypeIdle_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.IDLE;
+        assertThat(mPowerUsageSummary.shouldHideSipper(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSipper_TypeCell_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.CELL;
+        assertThat(mPowerUsageSummary.shouldHideSipper(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSipper_UidRoot_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
+        assertThat(mPowerUsageSummary.shouldHideSipper(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSipper_UidSystem_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(Process.SYSTEM_UID);
+        assertThat(mPowerUsageSummary.shouldHideSipper(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testShouldHideSipper_UidNormal_ReturnFalse() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(UID);
+        assertThat(mPowerUsageSummary.shouldHideSipper(mBatterySipper)).isFalse();
+    }
+
     public static class TestFragment extends PowerUsageSummary {
 
         private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
index 4d8101f..bb19533 100644
--- a/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/WorkSoundPreferenceControllerTest.java
@@ -114,17 +114,8 @@
                 .thenReturn(UserHandle.myUserId());
         when(mAudioHelper.isSingleVolume()).thenReturn(false);
         when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-        when(mScreen.findPreference(KEY_WORK_CATEGORY))
-            .thenReturn(mock(PreferenceGroup.class));
-        when(mScreen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS))
-            .thenReturn(mock(TwoStatePreference.class));
-        when(mScreen.findPreference(KEY_WORK_PHONE_RINGTONE))
-            .thenReturn(mock(DefaultRingtonePreference.class));
-        when(mScreen.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
-            .thenReturn(mock(DefaultRingtonePreference.class));
-        when(mScreen.findPreference(KEY_WORK_ALARM_RINGTONE))
-            .thenReturn(mock(DefaultRingtonePreference.class));
         when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);
+        mockWorkCategory();
 
         mController.onResume();
 
@@ -132,6 +123,50 @@
     }
 
     @Test
+    public void onManagedProfileAdded_shouldAddPreferenceCategory() {
+        // Given a device without any managed profiles:
+        when(mAudioHelper.isSingleVolume()).thenReturn(false);
+        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+        when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);
+        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+                .thenReturn(UserHandle.USER_NULL);
+        mockWorkCategory();
+
+        // When the fragment first resumes, the category should not appear.
+        mController.onResume();
+
+        verify(mFragment, never()).addPreferencesFromResource(R.xml.sound_work_settings);
+
+        // However, when a managed profile is added after resuming, the category should appear.
+        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+                .thenReturn(UserHandle.myUserId());
+        mController.onManagedProfileAdded(UserHandle.myUserId());
+
+        verify(mFragment).addPreferencesFromResource(R.xml.sound_work_settings);
+    }
+
+    @Test
+    public void onManagedProfileRemoved_shouldRemovePreferenceCategory() {
+        // Given a device with a managed profile:
+        when(mAudioHelper.isSingleVolume()).thenReturn(false);
+        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
+        when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext);
+        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+                .thenReturn(UserHandle.myUserId());
+        mockWorkCategory();
+
+        // Which is in resumed state:
+        mController.onResume();
+
+        // When a managed profile is removed, the category should be removed.
+        when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
+                .thenReturn(UserHandle.USER_NULL);
+        mController.onManagedProfileRemoved(UserHandle.myUserId());
+
+        verify(mScreen).removePreference(mScreen.findPreference(KEY_WORK_CATEGORY));
+    }
+
+    @Test
     public void onResume_notAvailable_shouldNotAddPreferenceCategory() {
         when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
         when(mAudioHelper.getManagedProfileId(any(UserManager.class)))
@@ -154,4 +189,16 @@
         verify(preference).setSummary(anyString());
     }
 
+    private void mockWorkCategory() {
+        when(mScreen.findPreference(KEY_WORK_CATEGORY))
+            .thenReturn(mock(PreferenceGroup.class));
+        when(mScreen.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS))
+            .thenReturn(mock(TwoStatePreference.class));
+        when(mScreen.findPreference(KEY_WORK_PHONE_RINGTONE))
+            .thenReturn(mock(DefaultRingtonePreference.class));
+        when(mScreen.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
+            .thenReturn(mock(DefaultRingtonePreference.class));
+        when(mScreen.findPreference(KEY_WORK_ALARM_RINGTONE))
+            .thenReturn(mock(DefaultRingtonePreference.class));
+    }
 }