Merge "Relax char length limits and add clarifications"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8ce83b4..c13e5f3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1862,35 +1862,43 @@
<!-- Exported for SystemUI to launch into -->
<activity android:name=".deviceinfo.StorageWizardInit"
- android:theme="@style/SuwThemeMaterial.Light"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardFormatConfirm"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardFormatProgress"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrate"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrateConfirm"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMigrateProgress"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardReady"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<activity android:name=".deviceinfo.StorageWizardMoveConfirm"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="false" />
<activity android:name=".deviceinfo.StorageWizardMoveProgress"
+ android:theme="@style/SetupWizardStorageStyle"
android:taskAffinity="com.android.settings.storage_wizard"
android:exported="true"
android:permission="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
diff --git a/res/drawable/ic_perm_device_information_red_24dp.xml b/res/drawable/ic_perm_device_information_red_24dp.xml
new file mode 100644
index 0000000..135e212
--- /dev/null
+++ b/res/drawable/ic_perm_device_information_red_24dp.xml
@@ -0,0 +1,27 @@
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorError">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M13,7h-2v2h2L13,7zM13,11h-2v6h2v-6zM17,1.01L7,1c-1.1,0 -2,0.9 -2,2v18c0,
+ 1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2L19,3c0,-1.1 -0.9,-1.99 -2,-1.99zM17,19L7,19L7,5h10v14z"/>
+</vector>
diff --git a/res/layout/storage_wizard_footer.xml b/res/layout/storage_wizard_footer.xml
new file mode 100644
index 0000000..f8384dc
--- /dev/null
+++ b/res/layout/storage_wizard_footer.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 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"
+ style="@style/SuwGlifButtonBar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
+
+ <Button
+ android:id="@+id/storage_next_button"
+ style="@style/SuwGlifButton.Primary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/suw_next_button_label" />
+
+</LinearLayout>
diff --git a/res/layout/storage_wizard_generic.xml b/res/layout/storage_wizard_generic.xml
index 3050c67..b6aab28 100644
--- a/res/layout/storage_wizard_generic.xml
+++ b/res/layout/storage_wizard_generic.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:suwBackgroundTile="@drawable/bg_tile_teal">
+ app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
@@ -49,4 +49,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/storage_wizard_init.xml b/res/layout/storage_wizard_init.xml
index 638bfe8..5fc298e 100644
--- a/res/layout/storage_wizard_init.xml
+++ b/res/layout/storage_wizard_init.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:suwBackgroundTile="@drawable/bg_tile_teal">
+ app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
@@ -66,4 +66,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/storage_wizard_migrate.xml b/res/layout/storage_wizard_migrate.xml
index 6d041fa..a1c1168 100644
--- a/res/layout/storage_wizard_migrate.xml
+++ b/res/layout/storage_wizard_migrate.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:suwBackgroundTile="@drawable/bg_tile_teal">
+ app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
@@ -58,4 +58,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/storage_wizard_progress.xml b/res/layout/storage_wizard_progress.xml
index e3b37f8..dbeaf66 100644
--- a/res/layout/storage_wizard_progress.xml
+++ b/res/layout/storage_wizard_progress.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:suwBackgroundTile="@drawable/bg_tile_teal">
+ app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
@@ -54,4 +54,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/layout/storage_wizard_ready.xml b/res/layout/storage_wizard_ready.xml
index d53038d..043b89f 100644
--- a/res/layout/storage_wizard_ready.xml
+++ b/res/layout/storage_wizard_ready.xml
@@ -14,13 +14,13 @@
limitations under the License.
-->
-<com.android.setupwizardlib.SetupWizardLayout
+<com.android.setupwizardlib.GlifLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- app:suwBackgroundTile="@drawable/bg_tile_teal">
+ app:suwFooter="@layout/storage_wizard_footer">
<LinearLayout
style="@style/SuwContentFrame"
@@ -39,4 +39,4 @@
</LinearLayout>
-</com.android.setupwizardlib.SetupWizardLayout>
+</com.android.setupwizardlib.GlifLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e1bcc36..08e992d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4755,6 +4755,10 @@
<string name="battery_tip_summary_title">Battery is in good shape</string>
<!-- Summary for the battery summary tip [CHAR LIMIT=NONE] -->
<string name="battery_tip_summary_summary">Apps are behaving normally</string>
+ <!-- Title for the low battery tip [CHAR LIMIT=NONE] -->
+ <string name="battery_tip_low_battery_title">Low battery capacity</string>
+ <!-- Summary for the low battery tip [CHAR LIMIT=NONE] -->
+ <string name="battery_tip_low_battery_summary">Battery can\'t provide good battery life</string>
<!-- Title for force stop dialog [CHAR LIMIT=30] -->
<string name="dialog_stop_title">Stop app?</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c68eb72..a07bade 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -362,8 +362,7 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
- <style name="SetupWizardStorageStyle" parent="@style/SuwThemeMaterial.Light">
- <item name="android:colorAccent">#ff009688</item>
+ <style name="SetupWizardStorageStyle" parent="@style/SuwThemeGlif.Light">
</style>
<style name="PreviewPagerPageIndicator">
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 96fe905..f8ac192 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -20,19 +20,9 @@
android:title="@string/location_settings_title"
settings:keywords="@string/keywords_location">
- <Preference
- android:key="location_mode"
- android:title="@string/location_mode_title"
- settings:keywords="@string/keywords_location_mode"
- android:summary="@string/summary_placeholder" />
-
- <!-- This preference category gets removed if there is no managed profile -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="managed_profile_location_switch"
- android:title="@string/managed_profile_location_switch_title"
- settings:useAdminDisabledSummary="true"
- android:enabled="false"
- android:selectable="true" />
+ <PreferenceCategory
+ android:key="recent_location_requests"
+ android:title="@string/location_category_recent_location_requests"/>
<!-- This preference category gets removed if new_recent_location_ui is disabled -->
<Preference
@@ -49,12 +39,21 @@
android:title="@string/location_scanning_screen_title"
android:fragment="com.android.settings.location.ScanningSettings"/>
- <PreferenceCategory
- android:key="recent_location_requests"
- android:title="@string/location_category_recent_location_requests" />
+ <!-- This preference category gets removed if there is no managed profile -->
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="managed_profile_location_switch"
+ android:title="@string/managed_profile_location_switch_title"
+ settings:useAdminDisabledSummary="true"
+ android:enabled="false"
+ android:selectable="true" />
<PreferenceCategory
android:key="location_services"
android:title="@string/location_category_location_services" />
+ <Preference
+ android:key="location_mode"
+ android:title="@string/location_mode_title"
+ settings:keywords="@string/keywords_location_mode"
+ android:summary="@string/summary_placeholder" />
</PreferenceScreen>
diff --git a/src/com/android/settings/applications/VrListenerSettings.java b/src/com/android/settings/applications/VrListenerSettings.java
index e40e3f9..ea88ae4 100644
--- a/src/com/android/settings/applications/VrListenerSettings.java
+++ b/src/com/android/settings/applications/VrListenerSettings.java
@@ -27,20 +27,16 @@
public class VrListenerSettings extends ManagedServiceSettings {
private static final String TAG = VrListenerSettings.class.getSimpleName();
- private static final Config CONFIG = getVrListenerConfig();
-
- private static final Config getVrListenerConfig() {
- final Config c = new Config();
- c.tag = TAG;
- c.setting = Settings.Secure.ENABLED_VR_LISTENERS;
- c.intentAction = VrListenerService.SERVICE_INTERFACE;
- c.permission = android.Manifest.permission.BIND_VR_LISTENER_SERVICE;
- c.noun = "vr listener";
- c.warningDialogTitle = R.string.vr_listener_security_warning_title;
- c.warningDialogSummary = R.string.vr_listener_security_warning_summary;
- c.emptyText = R.string.no_vr_listeners;
- return c;
- }
+ private static final Config CONFIG = new Config.Builder()
+ .setTag(TAG)
+ .setSetting(Settings.Secure.ENABLED_VR_LISTENERS)
+ .setIntentAction(VrListenerService.SERVICE_INTERFACE)
+ .setPermission(android.Manifest.permission.BIND_VR_LISTENER_SERVICE)
+ .setNoun("vr listener")
+ .setWarningDialogTitle(R.string.vr_listener_security_warning_title)
+ .setWarningDialogSummary(R.string.vr_listener_security_warning_summary)
+ .setEmptyText(R.string.no_vr_listeners)
+ .build();
@Override
protected Config getConfig() {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java
index c2ea2d2..5b48666 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardBase.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java
@@ -20,7 +20,9 @@
import android.annotation.LayoutRes;
import android.app.Activity;
-import android.graphics.Color;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.storage.DiskInfo;
@@ -30,16 +32,12 @@
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.settings.R;
-import com.android.setupwizardlib.SetupWizardLayout;
-import com.android.setupwizardlib.view.Illustration;
+import com.android.setupwizardlib.GlifLayout;
import java.text.NumberFormat;
import java.util.List;
@@ -51,8 +49,7 @@
protected VolumeInfo mVolume;
protected DiskInfo mDisk;
- private View mCustomNav;
- private Button mCustomNext;
+ private Button mNext;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -72,8 +69,6 @@
mDisk = mVolume.getDisk();
}
- setTheme(R.style.SetupWizardStorageStyle);
-
if (mDisk != null) {
mStorage.registerListener(mStorageListener);
}
@@ -83,53 +78,13 @@
public void setContentView(@LayoutRes int layoutResID) {
super.setContentView(layoutResID);
- // Our wizard is a unique flower, so it has custom buttons
- final ViewGroup navParent = (ViewGroup) findViewById(R.id.suw_layout_navigation_bar)
- .getParent();
- mCustomNav = getLayoutInflater().inflate(R.layout.storage_wizard_navigation,
- navParent, false);
-
- mCustomNext = (Button) mCustomNav.findViewById(R.id.suw_navbar_next);
- mCustomNext.setOnClickListener(new View.OnClickListener() {
+ mNext = (Button) findViewById(R.id.storage_next_button);
+ mNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onNavigateNext();
}
});
-
- // Swap our custom navigation bar into place
- for (int i = 0; i < navParent.getChildCount(); i++) {
- if (navParent.getChildAt(i).getId() == R.id.suw_layout_navigation_bar) {
- navParent.removeViewAt(i);
- navParent.addView(mCustomNav, i);
- break;
- }
- }
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
- final Window window = getWindow();
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS |
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
- WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
- window.setStatusBarColor(Color.TRANSPARENT);
-
- mCustomNav.setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-
- final View scrollView = findViewById(R.id.suw_bottom_scroll_view);
- scrollView.setVerticalFadingEdgeEnabled(true);
- scrollView.setFadingEdgeLength(scrollView.getVerticalFadingEdgeLength() * 2);
-
- if (findViewById(R.id.suw_layout_decor) instanceof Illustration) {
- // Our header illustration already have padding baked in
- final View title = findViewById(R.id.suw_layout_title);
- title.setPadding(title.getPaddingLeft(), 0, title.getPaddingRight(),
- title.getPaddingBottom());
- }
}
@Override
@@ -139,11 +94,11 @@
}
protected Button getNextButton() {
- return mCustomNext;
+ return mNext;
}
- protected SetupWizardLayout getSetupWizardLayout() {
- return (SetupWizardLayout) findViewById(R.id.setup_wizard_layout);
+ protected GlifLayout getGlifLayout() {
+ return (GlifLayout) findViewById(R.id.setup_wizard_layout);
}
protected ProgressBar getProgressBar() {
@@ -158,7 +113,7 @@
protected void setHeaderText(int resId, String... args) {
final CharSequence headerText = TextUtils.expandTemplate(getText(resId), args);
- getSetupWizardLayout().setHeaderText(headerText);
+ getGlifLayout().setHeaderText(headerText);
setTitle(headerText);
}
@@ -178,27 +133,16 @@
protected static final int ILLUSTRATION_PORTABLE = 2;
protected void setIllustrationType(int type) {
- switch (type) {
- case ILLUSTRATION_SETUP:
- getSetupWizardLayout().setIllustration(
- R.drawable.bg_setup_header,
- R.drawable.bg_header_horizontal_tile);
- break;
- case ILLUSTRATION_INTERNAL:
- getSetupWizardLayout().setIllustration(
- R.drawable.bg_internal_storage_header,
- R.drawable.bg_header_horizontal_tile);
- break;
- case ILLUSTRATION_PORTABLE:
- getSetupWizardLayout().setIllustration(
- R.drawable.bg_portable_storage_header,
- R.drawable.bg_header_horizontal_tile);
- break;
- }
+ // TODO: map type to updated icons once provided by UX
+ TypedArray array = obtainStyledAttributes(new int[] {android.R.attr.colorAccent});
+ Drawable icon = getDrawable(com.android.internal.R.drawable.ic_sd_card_48dp).mutate();
+ icon.setTint(array.getColor(0, 0));
+ array.recycle();
+ getGlifLayout().setIcon(icon);
}
protected void setKeepScreenOn(boolean keepScreenOn) {
- getSetupWizardLayout().setKeepScreenOn(keepScreenOn);
+ getGlifLayout().setKeepScreenOn(keepScreenOn);
}
public void onNavigateNext() {
diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java
index 3e1d86a..1d86999 100644
--- a/src/com/android/settings/display/TimeoutPreferenceController.java
+++ b/src/com/android/settings/display/TimeoutPreferenceController.java
@@ -65,7 +65,7 @@
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
final long maxTimeout =
- dpm.getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
+ dpm.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
timeoutListPreference.removeUnusableTimeouts(maxTimeout, admin);
}
updateTimeoutPreferenceDescription(timeoutListPreference, currentTimeout);
diff --git a/src/com/android/settings/fuelgauge/FakeUid.java b/src/com/android/settings/fuelgauge/FakeUid.java
index 2b5afe1..cbd9c3f 100644
--- a/src/com/android/settings/fuelgauge/FakeUid.java
+++ b/src/com/android/settings/fuelgauge/FakeUid.java
@@ -361,4 +361,14 @@
public long[] getScreenOffCpuFreqTimes(int which) {
return null;
}
+
+ @Override
+ public long[] getCpuFreqTimes(int procState, int which) {
+ return null;
+ }
+
+ @Override
+ public long[] getScreenOffCpuFreqTimes(int procState, int which) {
+ return null;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index b8cb6c4..9c3f48c 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -17,13 +17,21 @@
package com.android.settings.fuelgauge.batterytip;
import android.content.Context;
+import android.support.annotation.VisibleForTesting;
import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.fuelgauge.BatteryInfo;
+import com.android.settings.fuelgauge.BatteryUtils;
+import com.android.settings.fuelgauge.batterytip.detectors.BatteryTipDetector;
+import com.android.settings.fuelgauge.batterytip.detectors.LowBatteryDetector;
+import com.android.settings.fuelgauge.batterytip.detectors.SummaryDetector;
import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
import com.android.settingslib.utils.AsyncLoader;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -36,18 +44,31 @@
private static final boolean USE_FAKE_DATA = false;
private BatteryStatsHelper mBatteryStatsHelper;
+ private BatteryUtils mBatteryUtils;
+ @VisibleForTesting
+ int mVisibleTips;
public BatteryTipLoader(Context context, BatteryStatsHelper batteryStatsHelper) {
super(context);
mBatteryStatsHelper = batteryStatsHelper;
+ mBatteryUtils = BatteryUtils.getInstance(context);
}
@Override
public List<BatteryTip> loadInBackground() {
- List<BatteryTip> tips = new ArrayList<>();
+ if (USE_FAKE_DATA) {
+ return getFakeData();
+ }
+ final List<BatteryTip> tips = new ArrayList<>();
+ final BatteryTipPolicy policy = new BatteryTipPolicy(getContext());
+ final BatteryInfo batteryInfo = mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG);
+ mVisibleTips = 0;
- //TODO(b/70570352): add battery tip detectors
- tips.add(new SummaryTip(BatteryTip.StateType.NEW));
+ addBatteryTipFromDetector(tips, new LowBatteryDetector(policy, batteryInfo));
+ // Add summary detector at last since it need other detectors to update the mVisibleTips
+ addBatteryTipFromDetector(tips, new SummaryDetector(policy, mVisibleTips));
+
+ Collections.sort(tips);
return tips;
}
@@ -55,4 +76,20 @@
protected void onDiscardResult(List<BatteryTip> result) {
}
+ private List<BatteryTip> getFakeData() {
+ final List<BatteryTip> tips = new ArrayList<>();
+ tips.add(new SummaryTip(BatteryTip.StateType.NEW));
+ tips.add(new LowBatteryTip(BatteryTip.StateType.NEW));
+
+ return tips;
+ }
+
+ @VisibleForTesting
+ void addBatteryTipFromDetector(final List<BatteryTip> tips,
+ final BatteryTipDetector detector) {
+ final BatteryTip batteryTip = detector.detect();
+ mVisibleTips += batteryTip.isVisible() ? 1 : 0;
+ tips.add(batteryTip);
+ }
+
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java
new file mode 100644
index 0000000..ac5072d
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicy.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2017 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 android.content.Context;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.util.KeyValueListParser;
+import android.util.Log;
+
+/**
+ * Class to store the policy for battery tips, which comes from
+ * {@link Settings.Global}
+ */
+public class BatteryTipPolicy {
+ public static final String TAG = "BatteryTipPolicy";
+
+ private static final String KEY_BATTERY_TIP_ENABLED = "battery_tip_enabled";
+ private static final String KEY_SUMMARY_ENABLED = "summary_enabled";
+ private static final String KEY_BATTERY_SAVER_TIP_ENABLED = "battery_saver_tip_enabled";
+ private static final String KEY_HIGH_USAGE_ENABLED = "high_usage_enabled";
+ private static final String KEY_HIGH_USAGE_APP_COUNT = "high_usage_app_count";
+ private static final String KEY_APP_RESTRICTION_ENABLED = "app_restriction_enabled";
+ private static final String KEY_REDUCED_BATTERY_ENABLED = "reduced_battery_enabled";
+ private static final String KEY_REDUCED_BATTERY_PERCENT = "reduced_battery_percent";
+ private static final String KEY_LOW_BATTERY_ENABLED = "low_battery_enabled";
+ private static final String KEY_LOW_BATTERY_HOUR = "low_battery_hour";
+
+ /**
+ * {@code true} if general battery tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_BATTERY_TIP_ENABLED
+ */
+ public final boolean batteryTipEnabled;
+
+ /**
+ * {@code true} if summary tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_SUMMARY_ENABLED
+ */
+ public final boolean summaryEnabled;
+
+ /**
+ * {@code true} if battery saver tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_BATTERY_SAVER_TIP_ENABLED
+ */
+ public final boolean batterySaverTipEnabled;
+
+ /**
+ * {@code true} if high usage tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_HIGH_USAGE_ENABLED
+ */
+ public final boolean highUsageEnabled;
+
+ /**
+ * The maximum number of apps shown in high usage
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_HIGH_USAGE_APP_COUNT
+ */
+ public final int highUsageAppCount;
+
+ /**
+ * {@code true} if app restriction tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_APP_RESTRICTION_ENABLED
+ */
+ public final boolean appRestrictionEnabled;
+
+ /**
+ * {@code true} if reduced battery tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_REDUCED_BATTERY_ENABLED
+ */
+ public final boolean reducedBatteryEnabled;
+
+ /**
+ * The percentage of reduced battery to trigger the tip(e.g. 50%)
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_REDUCED_BATTERY_PERCENT
+ */
+ public final int reducedBatteryPercent;
+
+ /**
+ * {@code true} if low battery tip is enabled
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_LOW_BATTERY_ENABLED
+ */
+ public final boolean lowBatteryEnabled;
+
+ /**
+ * Remaining battery hour to trigger the tip(e.g. 16 hours)
+ *
+ * @see Settings.Global#BATTERY_TIP_CONSTANTS
+ * @see #KEY_LOW_BATTERY_HOUR
+ */
+ public final int lowBatteryHour;
+
+ private final KeyValueListParser mParser;
+
+ public BatteryTipPolicy(Context context) {
+ this(context, new KeyValueListParser(','));
+ }
+
+ @VisibleForTesting
+ BatteryTipPolicy(Context context, KeyValueListParser parser) {
+ mParser = parser;
+ final String value = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.BATTERY_TIP_CONSTANTS);
+
+ try {
+ mParser.setString(value);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Bad battery tip constants");
+ }
+
+ batteryTipEnabled = mParser.getBoolean(KEY_BATTERY_TIP_ENABLED, true);
+ summaryEnabled = mParser.getBoolean(KEY_SUMMARY_ENABLED, true);
+ batterySaverTipEnabled = mParser.getBoolean(KEY_BATTERY_SAVER_TIP_ENABLED, true);
+ highUsageEnabled = mParser.getBoolean(KEY_HIGH_USAGE_ENABLED, true);
+ highUsageAppCount = mParser.getInt(KEY_HIGH_USAGE_APP_COUNT, 3);
+ appRestrictionEnabled = mParser.getBoolean(KEY_APP_RESTRICTION_ENABLED, true);
+ reducedBatteryEnabled = mParser.getBoolean(KEY_REDUCED_BATTERY_ENABLED, true);
+ reducedBatteryPercent = mParser.getInt(KEY_REDUCED_BATTERY_PERCENT, 50);
+ lowBatteryEnabled = mParser.getBoolean(KEY_LOW_BATTERY_ENABLED, true);
+ lowBatteryHour = mParser.getInt(KEY_LOW_BATTERY_HOUR, 16);
+ }
+
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryTipDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryTipDetector.java
new file mode 100644
index 0000000..cb38e40
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/BatteryTipDetector.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 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.detectors;
+
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+
+public interface BatteryTipDetector {
+ /**
+ * Detect and update the status of {@link BatteryTip}
+ *
+ * @return a not null {@link BatteryTip}
+ */
+ BatteryTip detect();
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
new file mode 100644
index 0000000..2a6302e
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetector.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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.detectors;
+
+import android.text.format.DateUtils;
+
+import com.android.settings.fuelgauge.BatteryInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.fuelgauge.batterytip.tips.LowBatteryTip;
+
+/**
+ * Detect whether the battery is too low
+ */
+public class LowBatteryDetector implements BatteryTipDetector {
+ private BatteryInfo mBatteryInfo;
+ private BatteryTipPolicy mPolicy;
+
+ public LowBatteryDetector(BatteryTipPolicy policy, BatteryInfo batteryInfo) {
+ mPolicy = policy;
+ mBatteryInfo = batteryInfo;
+ }
+
+ @Override
+ public BatteryTip detect() {
+ // Show it if battery life is less than mPolicy.lowBatteryHour
+ final boolean isShown = mPolicy.lowBatteryEnabled && mBatteryInfo.discharging
+ && mBatteryInfo.remainingTimeUs < mPolicy.lowBatteryHour * DateUtils.HOUR_IN_MILLIS;
+ return new LowBatteryTip(
+ isShown ? BatteryTip.StateType.NEW : BatteryTip.StateType.INVISIBLE);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java
new file mode 100644
index 0000000..8c1783b
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetector.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017 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.detectors;
+
+import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.fuelgauge.batterytip.tips.SummaryTip;
+
+/**
+ * Detector whether to show summary tip. This detector should be executed as the last
+ * {@link BatteryTipDetector} since it need the most up-to-date {@code visibleTips}
+ */
+public class SummaryDetector implements BatteryTipDetector {
+ private BatteryTipPolicy mPolicy;
+ private int mVisibleTips;
+
+ public SummaryDetector(BatteryTipPolicy policy, int visibleTips) {
+ mPolicy = policy;
+ mVisibleTips = visibleTips;
+ }
+
+ @Override
+ public BatteryTip detect() {
+ // Show it if there is no other tips shown
+ final int state = mPolicy.summaryEnabled && mVisibleTips == 0
+ ? BatteryTip.StateType.NEW
+ : BatteryTip.StateType.INVISIBLE;
+ return new SummaryTip(state);
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index e633272..17e395e 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -31,7 +31,7 @@
* Each {@link BatteryTip} contains basic data(e.g. title, summary, icon) as well as the
* pre-defined action(e.g. turn on battery saver)
*/
-public abstract class BatteryTip {
+public abstract class BatteryTip implements Comparable<BatteryTip> {
@Retention(RetentionPolicy.SOURCE)
@IntDef({StateType.NEW,
StateType.HANDLED,
@@ -114,4 +114,13 @@
public int getState() {
return mState;
}
+
+ public boolean isVisible() {
+ return mState != StateType.INVISIBLE;
+ }
+
+ @Override
+ public int compareTo(BatteryTip o) {
+ return mType - o.mType;
+ }
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
new file mode 100644
index 0000000..8605fbb
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/LowBatteryTip.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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.tips;
+
+import android.app.Dialog;
+import android.content.Context;
+
+import com.android.settings.R;
+
+/**
+ * Tip to show current battery life is short
+ */
+public class LowBatteryTip extends BatteryTip {
+
+ public LowBatteryTip(@StateType int state) {
+ mShowDialog = false;
+ mState = state;
+ mType = TipType.LOW_BATTERY;
+ }
+
+ @Override
+ public CharSequence getTitle(Context context) {
+ return context.getString(R.string.battery_tip_low_battery_title);
+ }
+
+ @Override
+ public CharSequence getSummary(Context context) {
+ return context.getString(R.string.battery_tip_low_battery_summary);
+ }
+
+ @Override
+ public int getIconId() {
+ return R.drawable.ic_perm_device_information_red_24dp;
+ }
+
+ @Override
+ public void updateState(BatteryTip tip) {
+ mState = tip.mState;
+ }
+
+ @Override
+ public void action() {
+ // do nothing
+ }
+
+ @Override
+ public Dialog buildDialog() {
+ //TODO(b/70570352): create the dialog for low battery tip and add test
+ return null;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
index ab2a6c3..2a2deab 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/SummaryTip.java
@@ -29,6 +29,7 @@
public SummaryTip(@StateType int state) {
mShowDialog = false;
mState = state;
+ mType = TipType.SUMMARY;
}
@Override
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 3330421..1279d67 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -73,6 +73,16 @@
private LocationSwitchBarController mSwitchBarController;
@Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final RecentLocationApps recentLocationApps = new RecentLocationApps(getActivity());
+ int locationRequestsApps = recentLocationApps.getAppList().size();
+ int locationRequestsPrefs = locationRequestsApps == 0 ? 1 : locationRequestsApps;
+ getPreferenceScreen().setInitialExpandedChildrenCount(locationRequestsPrefs + 2);
+ }
+
+
+ @Override
public int getMetricsCategory() {
return MetricsEvent.LOCATION;
}
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index af89f49..4180a53 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -19,8 +19,9 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
+import android.app.NotificationManager;
import android.content.ComponentName;
-import android.content.DialogInterface;
+import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
@@ -33,22 +34,23 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.utils.ManagedServiceSettings;
+/**
+ * Settings screen for managing notification listener permissions
+ */
public class NotificationAccessSettings extends ManagedServiceSettings {
private static final String TAG = NotificationAccessSettings.class.getSimpleName();
- private static final Config CONFIG = getNotificationListenerConfig();
+ private static final Config CONFIG = new Config.Builder()
+ .setTag(TAG)
+ .setSetting(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS)
+ .setIntentAction(NotificationListenerService.SERVICE_INTERFACE)
+ .setPermission(android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE)
+ .setNoun("notification listener")
+ .setWarningDialogTitle(R.string.notification_listener_security_warning_title)
+ .setWarningDialogSummary(R.string.notification_listener_security_warning_summary)
+ .setEmptyText(R.string.no_notification_listeners)
+ .build();
- private static Config getNotificationListenerConfig() {
- final Config c = new Config();
- c.tag = TAG;
- c.setting = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
- c.intentAction = NotificationListenerService.SERVICE_INTERFACE;
- c.permission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
- c.noun = "notification listener";
- c.warningDialogTitle = R.string.notification_listener_security_warning_title;
- c.warningDialogSummary = R.string.notification_listener_security_warning_summary;
- c.emptyText = R.string.no_notification_listeners;
- return c;
- }
+ private NotificationManager mNm;
@Override
public int getMetricsCategory() {
@@ -56,6 +58,12 @@
}
@Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ mNm = context.getSystemService(NotificationManager.class);
+ }
+
+ @Override
protected Config getConfig() {
return CONFIG;
}
@@ -109,13 +117,10 @@
private static void disable(final NotificationAccessSettings parent, final ComponentName cn) {
parent.mNm.setNotificationListenerAccessGranted(cn, false);
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- if (!parent.mNm.isNotificationPolicyAccessGrantedForPackage(
- cn.getPackageName())) {
- parent.mNm.removeAutomaticZenRules(cn.getPackageName());
- }
+ AsyncTask.execute(() -> {
+ if (!parent.mNm.isNotificationPolicyAccessGrantedForPackage(
+ cn.getPackageName())) {
+ parent.mNm.removeAutomaticZenRules(cn.getPackageName());
}
});
}
@@ -153,16 +158,10 @@
.setMessage(summary)
.setCancelable(true)
.setPositiveButton(R.string.notification_listener_disable_warning_confirm,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- disable(parent, cn);
- }
- })
+ (dialog, id) -> disable(parent, cn))
.setNegativeButton(R.string.notification_listener_disable_warning_cancel,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- // pass
- }
+ (dialog, id) -> {
+ // pass
})
.create();
}
diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java
index 55d0fca..6ce13c1 100644
--- a/src/com/android/settings/notification/ZenModeAutomationSettings.java
+++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java
@@ -64,12 +64,12 @@
}
protected static ManagedServiceSettings.Config getConditionProviderConfig() {
- final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config();
- c.tag = TAG;
- c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
- c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
- c.noun = "condition provider";
- return c;
+ return new ManagedServiceSettings.Config.Builder()
+ .setTag(TAG)
+ .setIntentAction(ConditionProviderService.SERVICE_INTERFACE)
+ .setPermission(android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE)
+ .setNoun("condition provider")
+ .build();
}
/**
diff --git a/src/com/android/settings/search/indexing/PreIndexDataCollector.java b/src/com/android/settings/search/indexing/PreIndexDataCollector.java
index a4e1131..63000b4 100644
--- a/src/com/android/settings/search/indexing/PreIndexDataCollector.java
+++ b/src/com/android/settings/search/indexing/PreIndexDataCollector.java
@@ -287,8 +287,14 @@
String[] projection) {
final ContentResolver resolver = packageContext.getContentResolver();
- final Cursor cursor = resolver.query(uri, projection, null, null, null);
final List<String> result = new ArrayList<>();
+ Cursor cursor;
+ try {
+ cursor = resolver.query(uri, projection, null, null, null);
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Exception querying the keys!", e);
+ return result;
+ }
if (cursor == null) {
Log.w(TAG, "Cannot add index data for Uri: " + uri.toString());
diff --git a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
index 71c82f0..08e244e 100644
--- a/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
+++ b/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceController.java
@@ -107,8 +107,8 @@
if (mDPM != null) {
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(mContext);
- final long adminTimeout = mDPM
- .getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
+ final long adminTimeout =
+ mDPM.getMaximumTimeToLock(null /* admin */, UserHandle.myUserId());
final long displayTimeout = Math.max(0,
Settings.System.getInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
// This setting is a slave to display timeout when a device policy is enforced.
diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java
index d488dfe..d222345 100644
--- a/src/com/android/settings/utils/ManagedServiceSettings.java
+++ b/src/com/android/settings/utils/ManagedServiceSettings.java
@@ -21,11 +21,9 @@
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
-import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
@@ -33,8 +31,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceScreen;
import android.util.IconDrawableFactory;
import android.util.Log;
@@ -46,8 +42,8 @@
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.notification.EmptyTextSettings;
import com.android.settings.widget.AppSwitchPreference;
+import com.android.settingslib.applications.ServiceListing;
-import java.util.Collections;
import java.util.List;
public abstract class ManagedServiceSettings extends EmptyTextSettings {
@@ -57,8 +53,7 @@
protected Context mContext;
private PackageManager mPm;
private DevicePolicyManager mDpm;
- protected ServiceListing mServiceListing;
- protected NotificationManager mNm;
+ private ServiceListing mServiceListing;
private IconDrawableFactory mIconDrawableFactory;
abstract protected Config getConfig();
@@ -74,15 +69,15 @@
mContext = getActivity();
mPm = mContext.getPackageManager();
mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
- mServiceListing = new ServiceListing(mContext, mConfig);
- mServiceListing.addCallback(new ServiceListing.Callback() {
- @Override
- public void onServicesReloaded(List<ServiceInfo> services) {
- updateList(services);
- }
- });
+ mServiceListing = new ServiceListing.Builder(mContext)
+ .setPermission(mConfig.permission)
+ .setIntentAction(mConfig.intentAction)
+ .setNoun(mConfig.noun)
+ .setSetting(mConfig.setting)
+ .setTag(mConfig.tag)
+ .build();
+ mServiceListing.addCallback(this::updateList);
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(mContext));
}
@@ -115,7 +110,7 @@
final PreferenceScreen screen = getPreferenceScreen();
screen.removeAll();
- Collections.sort(services, new PackageItemInfo.DisplayNameComparator(mPm));
+ services.sort(new PackageItemInfo.DisplayNameComparator(mPm));
for (ServiceInfo service : services) {
final ComponentName cn = new ComponentName(service.packageName, service.name);
CharSequence title = null;
@@ -144,12 +139,9 @@
service.packageName, managedProfileId)) {
pref.setSummary(R.string.work_profile_notification_access_blocked_summary);
}
- pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean enable = (boolean) newValue;
- return setEnabled(cn, summary, enable);
- }
+ pref.setOnPreferenceChangeListener((preference, newValue) -> {
+ final boolean enable = (boolean) newValue;
+ return setEnabled(cn, summary, enable);
});
screen.addPreference(pref);
}
@@ -188,8 +180,8 @@
}
public static class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
- static final String KEY_COMPONENT = "c";
- static final String KEY_LABEL = "l";
+ private static final String KEY_COMPONENT = "c";
+ private static final String KEY_LABEL = "l";
@Override
public int getMetricsCategory() {
@@ -222,29 +214,92 @@
.setTitle(title)
.setCancelable(true)
.setPositiveButton(R.string.allow,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- parent.enable(cn);
- }
- })
+ (dialog, id) -> parent.enable(cn))
.setNegativeButton(R.string.deny,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int id) {
- // pass
- }
+ (dialog, id) -> {
+ // pass
})
.create();
}
}
public static class Config {
- public String tag;
- public String setting;
- public String intentAction;
- public String permission;
- public String noun;
- public int warningDialogTitle;
- public int warningDialogSummary;
- public int emptyText;
+ public final String tag;
+ public final String setting;
+ public final String intentAction;
+ public final String permission;
+ public final String noun;
+ public final int warningDialogTitle;
+ public final int warningDialogSummary;
+ public final int emptyText;
+
+ private Config(String tag, String setting, String intentAction, String permission,
+ String noun, int warningDialogTitle, int warningDialogSummary, int emptyText) {
+ this.tag = tag;
+ this.setting = setting;
+ this.intentAction = intentAction;
+ this.permission = permission;
+ this.noun = noun;
+ this.warningDialogTitle = warningDialogTitle;
+ this.warningDialogSummary = warningDialogSummary;
+ this.emptyText = emptyText;
+ }
+
+ public static class Builder{
+ private String mTag;
+ private String mSetting;
+ private String mIntentAction;
+ private String mPermission;
+ private String mNoun;
+ private int mWarningDialogTitle;
+ private int mWarningDialogSummary;
+ private int mEmptyText;
+
+ public Builder setTag(String tag) {
+ mTag = tag;
+ return this;
+ }
+
+ public Builder setSetting(String setting) {
+ mSetting = setting;
+ return this;
+ }
+
+ public Builder setIntentAction(String intentAction) {
+ mIntentAction = intentAction;
+ return this;
+ }
+
+ public Builder setPermission(String permission) {
+ mPermission = permission;
+ return this;
+ }
+
+ public Builder setNoun(String noun) {
+ mNoun = noun;
+ return this;
+ }
+
+ public Builder setWarningDialogTitle(int warningDialogTitle) {
+ mWarningDialogTitle = warningDialogTitle;
+ return this;
+ }
+
+ public Builder setWarningDialogSummary(int warningDialogSummary) {
+ mWarningDialogSummary = warningDialogSummary;
+ return this;
+ }
+
+ public Builder setEmptyText(int emptyText) {
+ mEmptyText = emptyText;
+ return this;
+ }
+
+ public Config build() {
+ return new Config(mTag, mSetting, mIntentAction, mPermission, mNoun,
+ mWarningDialogTitle, mWarningDialogSummary, mEmptyText);
+ }
+ }
}
+
}
diff --git a/src/com/android/settings/utils/ServiceListing.java b/src/com/android/settings/utils/ServiceListing.java
deleted file mode 100644
index 6a5fa10..0000000
--- a/src/com/android/settings/utils/ServiceListing.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.utils;
-
-import android.app.ActivityManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Slog;
-
-import com.android.settings.utils.ManagedServiceSettings.Config;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-
-public class ServiceListing {
- private final ContentResolver mContentResolver;
- private final Context mContext;
- private final Config mConfig;
- private final HashSet<ComponentName> mEnabledServices = new HashSet<ComponentName>();
- private final List<ServiceInfo> mServices = new ArrayList<ServiceInfo>();
- private final List<Callback> mCallbacks = new ArrayList<Callback>();
-
- private boolean mListening;
-
- public ServiceListing(Context context, Config config) {
- mContext = context;
- mConfig = config;
- mContentResolver = context.getContentResolver();
- }
-
- public void addCallback(Callback callback) {
- mCallbacks.add(callback);
- }
-
- public void removeCallback(Callback callback) {
- mCallbacks.remove(callback);
- }
-
- public void setListening(boolean listening) {
- if (mListening == listening) return;
- mListening = listening;
- if (mListening) {
- // listen for package changes
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
- filter.addDataScheme("package");
- mContext.registerReceiver(mPackageReceiver, filter);
- mContentResolver.registerContentObserver(Settings.Secure.getUriFor(mConfig.setting),
- false, mSettingsObserver);
- } else {
- mContext.unregisterReceiver(mPackageReceiver);
- mContentResolver.unregisterContentObserver(mSettingsObserver);
- }
- }
-
- public static int getEnabledServicesCount(Config config, Context context) {
- final String flat = Settings.Secure.getString(context.getContentResolver(), config.setting);
- if (flat == null || "".equals(flat)) return 0;
- final String[] components = flat.split(":");
- return components.length;
- }
-
- public static int getServicesCount(Config c, PackageManager pm) {
- return getServices(c, null, pm);
- }
-
- protected static int getServices(Config c, List<ServiceInfo> list, PackageManager pm) {
- int services = 0;
- if (list != null) {
- list.clear();
- }
- final int user = ActivityManager.getCurrentUser();
-
- List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
- new Intent(c.intentAction),
- PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
- user);
-
- for (int i = 0, count = installedServices.size(); i < count; i++) {
- ResolveInfo resolveInfo = installedServices.get(i);
- ServiceInfo info = resolveInfo.serviceInfo;
-
- if (!c.permission.equals(info.permission)) {
- Slog.w(c.tag, "Skipping " + c.noun + " service "
- + info.packageName + "/" + info.name
- + ": it does not require the permission "
- + c.permission);
- continue;
- }
- if (list != null) {
- list.add(info);
- }
- services++;
- }
- return services;
- }
-
- private void saveEnabledServices() {
- StringBuilder sb = null;
- for (ComponentName cn : mEnabledServices) {
- if (sb == null) {
- sb = new StringBuilder();
- } else {
- sb.append(':');
- }
- sb.append(cn.flattenToString());
- }
- Settings.Secure.putString(mContentResolver, mConfig.setting,
- sb != null ? sb.toString() : "");
- }
-
- private void loadEnabledServices() {
- mEnabledServices.clear();
- final String flat = Settings.Secure.getString(mContentResolver, mConfig.setting);
- if (flat != null && !"".equals(flat)) {
- final String[] names = flat.split(":");
- for (int i = 0; i < names.length; i++) {
- final ComponentName cn = ComponentName.unflattenFromString(names[i]);
- if (cn != null) {
- mEnabledServices.add(cn);
- }
- }
- }
- }
-
- public List<ServiceInfo> reload() {
- loadEnabledServices();
- getServices(mConfig, mServices, mContext.getPackageManager());
- for (Callback callback : mCallbacks) {
- callback.onServicesReloaded(mServices);
- }
- return mServices;
- }
-
- public boolean isEnabled(ComponentName cn) {
- return mEnabledServices.contains(cn);
- }
-
- public void setEnabled(ComponentName cn, boolean enabled) {
- if (enabled) {
- mEnabledServices.add(cn);
- } else {
- mEnabledServices.remove(cn);
- }
- saveEnabledServices();
- }
-
- private final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- reload();
- }
- };
-
- private final BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- reload();
- }
- };
-
- public interface Callback {
- void onServicesReloaded(List<ServiceInfo> services);
- }
-}
diff --git a/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java b/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java
index 2de964f..ccf6c53 100644
--- a/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java
+++ b/src/com/android/settings/wrapper/DevicePolicyManagerWrapper.java
@@ -223,7 +223,7 @@
*
* @see DevicePolicyManager#getMaximumTimeToLock(ComponentName, int)
*/
- public long getMaximumTimeToLockForUserAndProfiles(@UserIdInt int userHandle) {
- return mDpm.getMaximumTimeToLockForUserAndProfiles(userHandle);
+ public long getMaximumTimeToLock(@Nullable ComponentName admin, @UserIdInt int userHandle) {
+ return mDpm.getMaximumTimeToLock(admin, userHandle);
}
}
diff --git a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
index 80a8ade..33bc4f8 100644
--- a/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/TimeoutPreferenceControllerTest.java
@@ -88,8 +88,7 @@
final int profileUserId = UserHandle.myUserId();
final long timeout = 10000;
when(mUserManager.getProfiles(profileUserId)).thenReturn(Collections.emptyList());
- ShadowDevicePolicyManagerWrapper
- .setMaximumTimeToLockForUserAndProfiles(profileUserId, timeout);
+ ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(profileUserId, timeout);
mController.updateState(mPreference);
verify(mPreference).removeUnusableTimeouts(timeout, null);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
new file mode 100644
index 0000000..e4e8eef
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.batterytip.detectors.BatteryTipDetector;
+import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryTipLoaderTest {
+ @Mock
+ private BatteryStatsHelper mBatteryStatsHelper;
+ @Mock
+ private BatteryTipDetector mBatteryTipDetector;
+ @Mock
+ private BatteryTip mBatteryTip;
+ private Context mContext;
+ private BatteryTipLoader mBatteryTipLoader;
+ private List<BatteryTip> mBatteryTips;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ doReturn(mBatteryTip).when(mBatteryTipDetector).detect();
+ mBatteryTipLoader = new BatteryTipLoader(mContext, mBatteryStatsHelper);
+ mBatteryTips = new ArrayList<>();
+ }
+
+ @Test
+ public void testAddBatteryTipFromDetector_tipVisible_addAndUpdateCount() {
+ doReturn(true).when(mBatteryTip).isVisible();
+ mBatteryTipLoader.mVisibleTips = 0;
+
+ mBatteryTipLoader.addBatteryTipFromDetector(mBatteryTips, mBatteryTipDetector);
+
+ assertThat(mBatteryTips.contains(mBatteryTip)).isTrue();
+ assertThat(mBatteryTipLoader.mVisibleTips).isEqualTo(1);
+ }
+
+ @Test
+ public void testAddBatteryTipFromDetector_tipInvisible_doNotAddCount() {
+ doReturn(false).when(mBatteryTip).isVisible();
+ mBatteryTipLoader.mVisibleTips = 0;
+
+ mBatteryTipLoader.addBatteryTipFromDetector(mBatteryTips, mBatteryTipDetector);
+
+ assertThat(mBatteryTips.contains(mBatteryTip)).isTrue();
+ assertThat(mBatteryTipLoader.mVisibleTips).isEqualTo(0);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
new file mode 100644
index 0000000..1198b27
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipPolicyTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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 com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryTipPolicyTest {
+ private static final String BATTERY_TIP_CONSTANTS_VALUE = "battery_tip_enabled=true"
+ + ",summary_enabled=false"
+ + ",battery_saver_tip_enabled=false"
+ + ",high_usage_enabled=true"
+ + ",high_usage_app_count=5"
+ + ",app_restriction_enabled=true"
+ + ",reduced_battery_enabled=true"
+ + ",reduced_battery_percent=30"
+ + ",low_battery_enabled=false"
+ + ",low_battery_hour=10";
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void testInit_usesConfigValues() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.BATTERY_TIP_CONSTANTS, BATTERY_TIP_CONSTANTS_VALUE);
+
+ final BatteryTipPolicy batteryTipPolicy = new BatteryTipPolicy(mContext);
+
+ assertThat(batteryTipPolicy.batteryTipEnabled).isTrue();
+ assertThat(batteryTipPolicy.summaryEnabled).isFalse();
+ assertThat(batteryTipPolicy.batterySaverTipEnabled).isFalse();
+ assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
+ assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(5);
+ assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
+ assertThat(batteryTipPolicy.reducedBatteryEnabled).isTrue();
+ assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(30);
+ assertThat(batteryTipPolicy.lowBatteryEnabled).isFalse();
+ assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(10);
+ }
+
+ @Test
+ public void testInit_defaultValues() {
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.BATTERY_TIP_CONSTANTS, "");
+
+ final BatteryTipPolicy batteryTipPolicy = new BatteryTipPolicy(mContext);
+
+ assertThat(batteryTipPolicy.batteryTipEnabled).isTrue();
+ assertThat(batteryTipPolicy.summaryEnabled).isTrue();
+ assertThat(batteryTipPolicy.batterySaverTipEnabled).isTrue();
+ assertThat(batteryTipPolicy.highUsageEnabled).isTrue();
+ assertThat(batteryTipPolicy.highUsageAppCount).isEqualTo(3);
+ assertThat(batteryTipPolicy.appRestrictionEnabled).isTrue();
+ assertThat(batteryTipPolicy.reducedBatteryEnabled).isTrue();
+ assertThat(batteryTipPolicy.reducedBatteryPercent).isEqualTo(50);
+ assertThat(batteryTipPolicy.lowBatteryEnabled).isTrue();
+ assertThat(batteryTipPolicy.lowBatteryHour).isEqualTo(16);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java
new file mode 100644
index 0000000..4866a6a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/LowBatteryDetectorTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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.detectors;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+import android.text.format.DateUtils;
+
+import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.BatteryInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class LowBatteryDetectorTest {
+ private Context mContext;
+ @Mock
+ private BatteryInfo mBatteryInfo;
+ private BatteryTipPolicy mPolicy;
+ private LowBatteryDetector mLowBatteryDetector;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mPolicy = spy(new BatteryTipPolicy(mContext));
+ mLowBatteryDetector = new LowBatteryDetector(mPolicy, mBatteryInfo);
+ }
+
+ @Test
+ public void testDetect_disabledByPolicy_tipInvisible() {
+ ReflectionHelpers.setField(mPolicy, "lowBatteryEnabled", false);
+
+ assertThat(mLowBatteryDetector.detect().isVisible()).isFalse();
+ }
+
+ @Test
+ public void testDetect_shortBatteryLife_tipVisible() {
+ mBatteryInfo.discharging = true;
+ mBatteryInfo.remainingTimeUs = 1 * DateUtils.MINUTE_IN_MILLIS;
+
+ assertThat(mLowBatteryDetector.detect().isVisible()).isTrue();
+ }
+
+ @Test
+ public void testDetect_longBatteryLife_tipInvisible() {
+ mBatteryInfo.discharging = true;
+ mBatteryInfo.remainingTimeUs = 1 * DateUtils.DAY_IN_MILLIS;
+
+ assertThat(mLowBatteryDetector.detect().isVisible()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java
new file mode 100644
index 0000000..389a6c3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/SummaryDetectorTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2017 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.detectors;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SummaryDetectorTest {
+ private Context mContext;
+ private BatteryTipPolicy mPolicy;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mPolicy = spy(new BatteryTipPolicy(mContext));
+ }
+
+ @Test
+ public void testDetect_disabledByPolicy_tipInvisible() {
+ ReflectionHelpers.setField(mPolicy, "summaryEnabled", false);
+ SummaryDetector detector = new SummaryDetector(mPolicy, 0 /* visibleTips */);
+
+ assertThat(detector.detect().isVisible()).isFalse();
+ }
+
+ @Test
+ public void testDetect_noOtherTips_tipVisible() {
+ SummaryDetector detector = new SummaryDetector(mPolicy, 0 /* visibleTips */);
+
+ assertThat(detector.detect().isVisible()).isTrue();
+ }
+
+ @Test
+ public void testDetect_hasOtherTips_tipInVisible() {
+ SummaryDetector detector = new SummaryDetector(mPolicy, 1 /* visibleTips */);
+
+ assertThat(detector.detect().isVisible()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
index 4541e21..6afd25e 100644
--- a/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/screenlock/LockAfterTimeoutPreferenceControllerTest.java
@@ -129,8 +129,7 @@
when(mPreference.getEntryValues()).thenReturn(new CharSequence[] {"10000"} );
Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, displayTimeout);
- ShadowDevicePolicyManagerWrapper
- .setMaximumTimeToLockForUserAndProfiles(userId, adminTimeout);
+ ShadowDevicePolicyManagerWrapper.setMaximumTimeToLock(userId, adminTimeout);
mController.updateState((Preference) mPreference);
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java
index 46a0038..5502b37 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManagerWrapper.java
@@ -47,7 +47,7 @@
}
@Implementation
- public long getMaximumTimeToLockForUserAndProfiles(@UserIdInt int userHandle) {
+ public long getMaximumTimeToLock(ComponentName admin, @UserIdInt int userHandle) {
return profileTimeouts.getOrDefault(userHandle, 0L);
}
@@ -59,8 +59,7 @@
ShadowDevicePolicyManagerWrapper.deviceOwnerUserId = deviceOwnerUserId;
}
- public static void setMaximumTimeToLockForUserAndProfiles(
- @UserIdInt int userHandle, Long timeout) {
+ public static void setMaximumTimeToLock(@UserIdInt int userHandle, Long timeout) {
profileTimeouts.put(userHandle, timeout);
}
}