Add 3 controller for app usage page radio buttons

Bug: 178197718
Test: make SettingsRoboTests
Change-Id: I0b4cb6ca2db3c5f6dafd89484c91ca3f7fb1a1ae
diff --git a/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
new file mode 100644
index 0000000..b2da356
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/OptimizedPreferenceController.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.OPTIMIZED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class OptimizedPreferenceController extends AbstractPreferenceController
+        implements PreferenceControllerMixin {
+
+    private static final String TAG = "OPTIMIZED_PREF";
+
+    @VisibleForTesting String KEY_OPTIMIZED_PREF = "optimized_pref";
+    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+    public OptimizedPreferenceController(Context context, int uid, String packageName) {
+        super(context);
+        mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        if (!mBatteryOptimizeUtils.isValidPackageName()) {
+            Log.d(TAG, "invalid package name, optimized states only");
+            preference.setEnabled(true);
+            ((RadioButtonPreference) preference).setChecked(true);
+            return;
+        }
+
+        if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+            Log.d(TAG, "is system or default app, disable pref");
+            ((RadioButtonPreference) preference).setChecked(false);
+            preference.setEnabled(false);
+        } else if (mBatteryOptimizeUtils.getAppUsageState() == OPTIMIZED) {
+            Log.d(TAG, "is optimized states");
+            ((RadioButtonPreference) preference).setChecked(true);
+        } else {
+            ((RadioButtonPreference) preference).setChecked(false);
+        }
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_OPTIMIZED_PREF;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!KEY_OPTIMIZED_PREF.equals(preference.getKey())) {
+            return false;
+        }
+
+        mBatteryOptimizeUtils.setAppUsageState(OPTIMIZED);
+        Log.d(TAG, "Set optimized");
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
new file mode 100644
index 0000000..b52af57
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/RestrictedPreferenceController.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.RESTRICTED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class RestrictedPreferenceController extends AbstractPreferenceController
+        implements PreferenceControllerMixin {
+
+    private static final String TAG = "RESTRICTED_PREF";
+
+    @VisibleForTesting String KEY_RESTRICTED_PREF = "restricted_pref";
+    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+    public RestrictedPreferenceController(Context context, int uid, String packageName) {
+        super(context);
+        mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+
+        if (!mBatteryOptimizeUtils.isValidPackageName()) {
+            Log.d(TAG, "invalid package name, disable pref");
+            preference.setEnabled(false);
+            return;
+        } else {
+            preference.setEnabled(true);
+        }
+
+        if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+            Log.d(TAG, "is system or default app, disable pref");
+            ((RadioButtonPreference) preference).setChecked(false);
+            preference.setEnabled(false);
+        } else if (mBatteryOptimizeUtils.getAppUsageState() == RESTRICTED) {
+            Log.d(TAG, "is restricted states");
+            ((RadioButtonPreference) preference).setChecked(true);
+        } else {
+            ((RadioButtonPreference) preference).setChecked(false);
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_RESTRICTED_PREF;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!KEY_RESTRICTED_PREF.equals(preference.getKey())) {
+            return false;
+        }
+
+        mBatteryOptimizeUtils.setAppUsageState(RESTRICTED);
+        Log.d(TAG, "Set restricted");
+        return true;
+    }
+}
diff --git a/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
new file mode 100644
index 0000000..36141c5
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/UnrestrictedPreferenceController.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.android.settings.fuelgauge.BatteryOptimizeUtils.AppUsageState.UNRESTRICTED;
+
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+public class UnrestrictedPreferenceController extends AbstractPreferenceController
+        implements PreferenceControllerMixin {
+
+    private static final String TAG = "UNRESTRICTED_PREF";
+
+    @VisibleForTesting String KEY_UNRESTRICTED_PREF = "unrestricted_pref";
+    @VisibleForTesting BatteryOptimizeUtils mBatteryOptimizeUtils;
+
+    public UnrestrictedPreferenceController(Context context, int uid, String packageName) {
+        super(context);
+        mBatteryOptimizeUtils = new BatteryOptimizeUtils(context, uid, packageName);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+
+        if (!mBatteryOptimizeUtils.isValidPackageName()) {
+            Log.d(TAG, "invalid package name, disable pref");
+            preference.setEnabled(false);
+            return;
+        } else {
+            preference.setEnabled(true);
+        }
+
+        if (mBatteryOptimizeUtils.isSystemOrDefaultApp()) {
+            Log.d(TAG, "is system or default app, unrestricted states only");
+            ((RadioButtonPreference) preference).setChecked(true);
+        } else if (mBatteryOptimizeUtils.getAppUsageState() == UNRESTRICTED) {
+            Log.d(TAG, "is unrestricted states");
+            ((RadioButtonPreference) preference).setChecked(true);
+        } else {
+            ((RadioButtonPreference) preference).setChecked(false);
+        }
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    @Override
+    public String getPreferenceKey() {
+        return KEY_UNRESTRICTED_PREF;
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!KEY_UNRESTRICTED_PREF.equals(preference.getKey())) {
+            return false;
+        }
+
+        mBatteryOptimizeUtils.setAppUsageState(UNRESTRICTED);
+        Log.d(TAG, "Set unrestricted");
+        return true;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
new file mode 100644
index 0000000..874618d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/OptimizedPreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class OptimizedPreferenceControllerTest {
+    private static final int UID = 12345;
+    private static final String PACKAGE_NAME = "com.android.app";
+
+    private OptimizedPreferenceController mController;
+    private RadioButtonPreference mPreference;
+
+    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new OptimizedPreferenceController(
+                RuntimeEnvironment.application, UID, PACKAGE_NAME);
+        mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+    }
+
+    @Test
+    public void testUpdateState_invalidPackage_prefEnabled() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_isSystemOrDefaultApp_prefUnchecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isOptimizedStates_prefChecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+                BatteryOptimizeUtils.AppUsageState.OPTIMIZED);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_prefUnchecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+        mPreference.setKey(mController.KEY_OPTIMIZED_PREF);
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mockBatteryOptimizeUtils).setAppUsageState(
+                BatteryOptimizeUtils.AppUsageState.OPTIMIZED);
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verifyZeroInteractions(mockBatteryOptimizeUtils);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
new file mode 100644
index 0000000..2e17404
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class RestrictedPreferenceControllerTest {
+    private static final int UID = 12345;
+    private static final String PACKAGE_NAME = "com.android.app";
+
+    private RestrictedPreferenceController mController;
+    private RadioButtonPreference mPreference;
+
+    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new RestrictedPreferenceController(
+                RuntimeEnvironment.application, UID, PACKAGE_NAME);
+        mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+    }
+
+    @Test
+    public void testUpdateState_isValidPackage_prefEnabled() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_invalidPackage_prefDisabled() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isRestrictedStates_prefChecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+                BatteryOptimizeUtils.AppUsageState.RESTRICTED);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_prefUnchecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+        mPreference.setKey(mController.KEY_RESTRICTED_PREF);
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mockBatteryOptimizeUtils).setAppUsageState(
+                BatteryOptimizeUtils.AppUsageState.RESTRICTED);
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verifyZeroInteractions(mockBatteryOptimizeUtils);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
new file mode 100644
index 0000000..63cf760
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/UnrestrictedPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class UnrestrictedPreferenceControllerTest {
+    private static final int UID = 12345;
+    private static final String PACKAGE_NAME = "com.android.app";
+
+    private UnrestrictedPreferenceController mController;
+    private RadioButtonPreference mPreference;
+
+    @Mock BatteryOptimizeUtils mockBatteryOptimizeUtils;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new UnrestrictedPreferenceController(
+                RuntimeEnvironment.application, UID, PACKAGE_NAME);
+        mPreference = new RadioButtonPreference(RuntimeEnvironment.application);
+        mController.mBatteryOptimizeUtils = mockBatteryOptimizeUtils;
+    }
+
+    @Test
+    public void testUpdateState_isValidPackage_prefEnabled() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_invalidPackage_prefDisabled() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(false);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isEnabled()).isFalse();
+    }
+
+    @Test
+    public void testUpdateState_isSystemOrDefaultApp_prefChecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.isSystemOrDefaultApp()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_isUnrestrictedStates_prefChecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+        when(mockBatteryOptimizeUtils.getAppUsageState()).thenReturn(
+                BatteryOptimizeUtils.AppUsageState.UNRESTRICTED);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void testUpdateState_prefUnchecked() {
+        when(mockBatteryOptimizeUtils.isValidPackageName()).thenReturn(true);
+
+        mController.updateState(mPreference);
+
+        assertThat(mPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_samePrefKey_verifyAction() {
+        mPreference.setKey(mController.KEY_UNRESTRICTED_PREF);
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verify(mockBatteryOptimizeUtils).setAppUsageState(
+                BatteryOptimizeUtils.AppUsageState.UNRESTRICTED);
+    }
+
+    @Test
+    public void testHandlePreferenceTreeClick_incorrectPrefKey_noAction() {
+        mController.handlePreferenceTreeClick(mPreference);
+
+        verifyZeroInteractions(mockBatteryOptimizeUtils);
+    }
+}