Merge "Link to "scanning settings" when Wi-Fi is off." into oc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 543c90b..da88f76 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2558,6 +2558,7 @@
<intent-filter android:priority="1">
<action android:name="com.android.settings.SOUND_SETTINGS" />
<action android:name="android.settings.SOUND_SETTINGS" />
+ <action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -2566,10 +2567,6 @@
<category android:name="android.intent.category.VOICE_LAUNCH" />
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
- <intent-filter android:priority="1">
- <action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
<intent-filter android:priority="6">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml
index ef39d8b..04ef74d 100644
--- a/res/layout/battery_header.xml
+++ b/res/layout/battery_header.xml
@@ -27,44 +27,35 @@
android:background="@drawable/selectable_card_grey"
style="@style/EntityHeader">
- <com.android.settings.fuelgauge.BatteryMeterView
- android:id="@+id/battery_header_icon"
- android:layout_width="@dimen/battery_meter_width"
- android:layout_height="@dimen/battery_meter_height"/>
-
<LinearLayout
- android:layout_width="wrap_content"
+ android:layout_width="216dp"
android:layout_height="wrap_content"
- android:layout_marginStart="12dp"
+ android:layout_marginStart="48dp"
android:layout_marginEnd="12dp"
android:orientation="vertical">
<TextView
- android:id="@+id/time"
+ android:id="@+id/battery_percent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
- android:gravity="center"
- android:textAppearance="@android:style/TextAppearance.Material.Medium"/>
+ android:textAppearance="@android:style/TextAppearance.Material.Display1"/>
<TextView
android:id="@+id/summary1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
- android:gravity="center"
android:textAppearance="@android:style/TextAppearance.Material.Small"
android:text="@string/estimated_time_left"/>
- <TextView
- android:id="@+id/summary2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="12dp"
- android:gravity="center"
- android:textAppearance="@android:style/TextAppearance.Material.Small"
- android:text="@string/estimated_time_description"/>
-
</LinearLayout>
+ <com.android.settings.fuelgauge.BatteryMeterView
+ android:id="@+id/battery_header_icon"
+ android:layout_width="@dimen/battery_meter_width"
+ android:layout_height="@dimen/battery_meter_height"
+ android:layout_gravity="end"
+ android:layout_marginEnd="24dp"/>
+
</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c472858..2dbd222 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -765,6 +765,8 @@
<string name="security_status_title">Security status</string>
<!-- Summary for Security settings, explaining a few important settings under it [CHAR LIMIT=NONE]-->
<string name="security_dashboard_summary">Location, fingerprint</string>
+ <!-- Summary for Security settings when fingerprint is not supported [CHAR LIMIT=NONE]-->
+ <string name="security_dashboard_summary_no_fingerprint">Location</string>
<!-- Fingerprint enrollment and settings --><skip />
<!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
<string name="security_settings_fingerprint_preference_title">Fingerprint</string>
@@ -3887,13 +3889,6 @@
<string name="show_password">Show passwords</string>
<!-- On Security & location settings screen. This is a short summary text describing what "Show passwords" setting does -->
<string name="show_password_summary">Display characters briefly as you type</string>
- <!-- Warning message about security implications of enabling an input method, displayed as a dialog
- message when the user selects to enable an IME. -->
- <string name="ime_security_warning">This input method may be able to collect
- all the text you type, including personal data like passwords and credit
- card numbers. It comes from the app
- <xliff:g id="ime_application_name">%1$s</xliff:g>.
- Use this input method?</string>
<!-- Warning message about security implications of enabling a spell checker, displayed as a dialog
message when the user selects to enable a spell checker. -->
<string name="spellchecker_security_warning">This spell checker may be able to collect
@@ -3905,9 +3900,6 @@
<string name="spellchecker_quick_settings">Settings</string>
<!-- Image button description for spell checker language. -->
<string name="spellchecker_language">Language</string>
- <!-- Toast that settings for an application is failed to open. -->
- <string name="failed_to_open_app_settings_toast">Failed to open settings for <xliff:g id="spell_application_name">%1$s</xliff:g></string>
-
<!-- Title for the 'keyboard and input methods' preference category. [CHAR LIMIT=45] -->
<string name="keyboard_and_input_methods_category">Keyboard & inputs</string>
<!-- Title for the 'virtual keyboard' preference sub-screen. [CHAR LIMIT=35] -->
@@ -7407,7 +7399,7 @@
Allowing <xliff:g id="app_name" example="Settings">%1$s</xliff:g> to always run in the background may reduce battery life.
\n\nYou can change this later from Settings > Apps & notifications.</string>
<!-- Summary of power usage for an app [CHAR LIMIT=NONE] -->
- <string name="battery_summary"><xliff:g id="percentage" example="2">%1$d</xliff:g>%% use since last full charge</string>
+ <string name="battery_summary"><xliff:g id="percentage" example="2">%1$s</xliff:g> use since last full charge</string>
<!-- Title of a group of settings that let you manage settings that affect battery life [CHAR LIMIT=60] -->
<string name="battery_power_management">Power management</string>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index a387813..b486776 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -26,6 +26,19 @@
android:layout="@layout/battery_header"/>
<PreferenceCategory
+ android:key="device_usage_list">
+
+ <com.android.settings.fuelgauge.PowerGaugePreference
+ android:key="last_full_charge"
+ android:title="@string/battery_last_full_charge"/>
+
+ <com.android.settings.fuelgauge.PowerGaugePreference
+ android:key="screen_usage"
+ android:title="@string/device_screen_usage"/>
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
android:key="power_management"
android:title="@string/battery_power_management">
@@ -60,22 +73,4 @@
android:key="app_list"
android:title="@string/power_usage_list_summary"/>
- <PreferenceCategory
- android:key="device_usage_list"
- android:title="@string/device_usage_list_summary">
-
- <Preference
- android:key="screen_usage"
- android:title="@string/device_screen_usage"/>
-
- <Preference
- android:key="screen_consumption"
- android:title="@string/device_screen_consumption"/>
-
- <Preference
- android:key="cellular_network"
- android:title="@string/device_cellular_network"/>
-
- </PreferenceCategory>
-
</PreferenceScreen>
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 47ea5b6..9967918 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -89,6 +89,7 @@
import com.android.settings.datausage.AppDataUsage;
import com.android.settings.datausage.DataUsageList;
import com.android.settings.datausage.DataUsageSummary;
+import com.android.settings.fuelgauge.AdvancedPowerUsageDetail;
import com.android.settings.fuelgauge.BatteryEntry;
import com.android.settings.fuelgauge.PowerUsageDetail;
import com.android.settings.notification.AppNotificationSettings;
@@ -183,10 +184,12 @@
private ChartData mChartData;
private INetworkStatsSession mStatsSession;
- private Preference mBatteryPreference;
-
- private BatteryStatsHelper mBatteryHelper;
- private BatterySipper mSipper;
+ @VisibleForTesting
+ Preference mBatteryPreference;
+ @VisibleForTesting
+ BatterySipper mSipper;
+ @VisibleForTesting
+ BatteryStatsHelper mBatteryHelper;
protected ProcStatsData mStatsManager;
protected ProcStatsPackageEntry mStats;
@@ -194,6 +197,7 @@
private InstantAppButtonsController mInstantAppButtonsController;
private AppStorageStats mLastResult;
+ private String mBatteryPercent;
private boolean handleDisableable(Button button) {
boolean disableable = false;
@@ -686,7 +690,8 @@
BatteryStats.STATS_SINCE_CHARGED);
final int percentOfMax = (int) ((mSipper.totalPowerMah)
/ mBatteryHelper.getTotalPower() * dischargeAmount + .5f);
- mBatteryPreference.setSummary(getString(R.string.battery_summary, percentOfMax));
+ mBatteryPercent = Utils.formatPercentage(percentOfMax);
+ mBatteryPreference.setSummary(getString(R.string.battery_summary, mBatteryPercent));
} else {
mBatteryPreference.setEnabled(false);
mBatteryPreference.setSummary(getString(R.string.no_battery_summary));
@@ -718,7 +723,7 @@
? R.string.storage_type_external
: R.string.storage_type_internal);
return context.getString(R.string.storage_summary_format,
- getSize(context, stats), storageType);
+ getSize(context, stats), storageType.toString().toLowerCase());
}
}
@@ -960,9 +965,9 @@
} else if (preference == mDataPreference) {
startAppInfoFragment(AppDataUsage.class, getString(R.string.app_data_usage));
} else if (preference == mBatteryPreference) {
- BatteryEntry entry = new BatteryEntry(getActivity(), null, mUserManager, mSipper);
- PowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this,
- mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, true, false);
+ BatteryEntry entry = new BatteryEntry(getContext(), null, mUserManager, mSipper);
+ AdvancedPowerUsageDetail.startBatteryDetailPage((SettingsActivity) getActivity(), this,
+ mBatteryHelper, BatteryStats.STATS_SINCE_CHARGED, entry, mBatteryPercent);
} else {
return false;
}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
index ce9344f..d943de7 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
@@ -22,7 +22,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
-import android.service.autofill.AutoFillService;
import android.service.autofill.AutofillService;
import android.service.autofill.AutofillServiceInfo;
import android.text.TextUtils;
@@ -36,8 +35,6 @@
public class DefaultAutofillPicker extends DefaultAppPickerFragment {
static final String SETTING = Settings.Secure.AUTOFILL_SERVICE;
- // TODO(b/35956626): remove once clients migrated
- static final Intent OLD_AUTO_FILL_PROBE = new Intent(AutoFillService.OLD_SERVICE_INTERFACE);
static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE);
@Override
@@ -59,12 +56,6 @@
candidates.add(new DefaultAppInfo(mPm, mUserId, new ComponentName(
info.serviceInfo.packageName, info.serviceInfo.name)));
}
- final List<ResolveInfo> oldResolveInfos = mPm.getPackageManager()
- .queryIntentServices(OLD_AUTO_FILL_PROBE, PackageManager.GET_META_DATA);
- for (ResolveInfo info : oldResolveInfos) {
- candidates.add(new DefaultAppInfo(mPm, mUserId, new ComponentName(
- info.serviceInfo.packageName, info.serviceInfo.name)));
- }
return candidates;
}
@@ -122,24 +113,6 @@
}
}
- final List<ResolveInfo> oldResolveInfos = mPackageManager.queryIntentServices(
- OLD_AUTO_FILL_PROBE, PackageManager.GET_META_DATA);
-
- for (ResolveInfo resolveInfo : oldResolveInfos) {
- final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
- final String flattenKey = new ComponentName(
- serviceInfo.packageName, serviceInfo.name).flattenToString();
- if (TextUtils.equals(mSelectedKey, flattenKey)) {
- final String settingsActivity = new AutofillServiceInfo(
- mPackageManager, serviceInfo)
- .getSettingsActivity();
- if (TextUtils.isEmpty(settingsActivity)) {
- return null;
- }
- return new Intent(Intent.ACTION_MAIN).setComponent(
- new ComponentName(serviceInfo.packageName, settingsActivity));
- }
- }
return null;
}
}
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
index 9127782..dcbf472 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -46,7 +46,7 @@
mDrawable = new BatteryMeterDrawable(context, frameColor);
mDrawable.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
- mDrawable.setShowPercent(true);
+ mDrawable.setShowPercent(false);
setImageDrawable(mDrawable);
}
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index d4f2dd2..bdadf4c 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -29,8 +29,11 @@
import com.android.settings.Utils;
/**
- * Custom preference for displaying power consumption as a bar and an icon on
+ * Custom preference for displaying battery usage info as a bar and an icon on
* the left for the subsystem/app type.
+ *
+ * The battery usage info could be usage percentage or usage time. The preference
+ * won't show any icon if it is null.
*/
public class PowerGaugePreference extends TintablePreference {
private final int mIconSize;
@@ -41,7 +44,20 @@
public PowerGaugePreference(Context context, Drawable icon, CharSequence contentDescription,
BatteryEntry info) {
- super(context, null);
+ this(context, null, icon, contentDescription, info);
+ }
+
+ public PowerGaugePreference(Context context) {
+ this(context, null, null, null, null);
+ }
+
+ public PowerGaugePreference(Context context, AttributeSet attrs) {
+ this(context, attrs, null, null, null);
+ }
+
+ private PowerGaugePreference(Context context, AttributeSet attrs, Drawable icon,
+ CharSequence contentDescription, BatteryEntry info) {
+ super(context, attrs);
setIcon(icon != null ? icon : new ColorDrawable(0));
setWidgetLayoutResource(R.layout.preference_widget_summary);
mInfo = info;
@@ -49,10 +65,6 @@
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
}
- public PowerGaugePreference(Context context) {
- this(context, null, null, null);
- }
-
public void setContentDescription(String name) {
mContentDescription = name;
notifyChanged();
@@ -67,6 +79,11 @@
return mProgress.toString();
}
+ public void setSubtitle(String subtitle) {
+ mProgress = subtitle;
+ notifyChanged();
+ }
+
BatteryEntry getInfo() {
return mInfo;
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 96141f9..2c1fd78 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -16,7 +16,6 @@
package com.android.settings.fuelgauge;
-import android.annotation.StringRes;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -26,6 +25,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.Process;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
@@ -39,7 +39,6 @@
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -60,6 +59,7 @@
import com.android.settings.display.TimeoutPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.FooterPreferenceMixin;
import com.android.settingslib.BatteryInfo;
import java.util.ArrayList;
@@ -87,8 +87,7 @@
private static final int SECONDS_IN_HOUR = 60 * 60;
private static final String KEY_SCREEN_USAGE = "screen_usage";
- private static final String KEY_SCREEN_CONSUMPTION = "screen_consumption";
- private static final String KEY_CELLULAR_NETWORK = "cellular_network";
+ private static final String KEY_TIME_SINCE_LAST_FULL_CHARGE = "last_full_charge";
private static final int MENU_STATS_TYPE = Menu.FIRST;
@@ -100,14 +99,15 @@
static final int MENU_TOGGLE_APPS = Menu.FIRST + 5;
private static final int MENU_HELP = Menu.FIRST + 6;
+ private final FooterPreferenceMixin mFooterPreferenceMixin =
+ new FooterPreferenceMixin(this, getLifecycle());
+
@VisibleForTesting
boolean mShowAllApps = false;
@VisibleForTesting
- Preference mScreenUsagePref;
+ PowerGaugePreference mScreenUsagePref;
@VisibleForTesting
- Preference mScreenConsumptionPref;
- @VisibleForTesting
- Preference mCellularNetworkPref;
+ PowerGaugePreference mLastFullChargePref;
@VisibleForTesting
PowerUsageFeatureProvider mPowerFeatureProvider;
@@ -122,9 +122,10 @@
mBatteryLayoutPref = (LayoutPreference) findPreference(KEY_BATTERY_HEADER);
mAppListGroup = (PreferenceGroup) findPreference(KEY_APP_LIST);
- mScreenUsagePref = findPreference(KEY_SCREEN_USAGE);
- mScreenConsumptionPref = findPreference(KEY_SCREEN_CONSUMPTION);
- mCellularNetworkPref = findPreference(KEY_CELLULAR_NETWORK);
+ mScreenUsagePref = (PowerGaugePreference) findPreference(KEY_SCREEN_USAGE);
+ mLastFullChargePref = (PowerGaugePreference) findPreference(
+ KEY_TIME_SINCE_LAST_FULL_CHARGE);
+ mFooterPreferenceMixin.createFooterPreference().setTitle(R.string.battery_footer_summary);
initFeatureProvider();
}
@@ -417,8 +418,11 @@
final int dischargeAmount = USE_FAKE_DATA ? 5000
: stats != null ? stats.getDischargeAmount(mStatsType) : 0;
- updateScreenPreference(dischargeAmount);
- updateCellularPreference(dischargeAmount);
+ final long runningTime = calculateRunningTimeBasedOnStatsType();
+ updateScreenPreference();
+ updateLastFullChargePreference(runningTime);
+ mAppListGroup.setTitle(getString(R.string.power_usage_list_summary,
+ Utils.formatElapsedTime(context, runningTime, false)));
if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) {
final List<BatterySipper> usageList = getCoalescedUsageList(
@@ -527,28 +531,27 @@
}
@VisibleForTesting
- void updateScreenPreference(final int dischargeAmount) {
+ void updateScreenPreference() {
final BatterySipper sipper = findBatterySipperByType(
mStatsHelper.getUsageList(), DrainType.SCREEN);
final Context context = getContext();
- final double totalPowerMah = sipper != null ? sipper.totalPowerMah : 0;
final long usageTimeMs = sipper != null ? sipper.usageTimeMs : 0;
- final double percentOfTotal = calculatePercentage(totalPowerMah, dischargeAmount);
- mScreenUsagePref.setSummary(getString(R.string.battery_used_for,
- Utils.formatElapsedTime(context, usageTimeMs, false)));
- mScreenConsumptionPref.setSummary(getString(R.string.battery_overall_usage,
- Utils.formatPercentage(percentOfTotal, true)));
+ mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(context, usageTimeMs, false));
}
@VisibleForTesting
- void updateCellularPreference(final int dischargeAmount) {
- final BatterySipper sipper = findBatterySipperByType(
- mStatsHelper.getUsageList(), DrainType.CELL);
- final double totalPowerMah = sipper != null ? sipper.totalPowerMah : 0;
- final double percentOfTotal = calculatePercentage(totalPowerMah, dischargeAmount);
- mCellularNetworkPref.setSummary(getString(R.string.battery_overall_usage,
- Utils.formatPercentage(percentOfTotal, true)));
+ void updateLastFullChargePreference(long timeMs) {
+ mLastFullChargePref.setSubtitle(getString(R.string.power_last_full_charge_summary,
+ Utils.formatElapsedTime(getContext(), timeMs, false)));
+ }
+
+ @VisibleForTesting
+ long calculateRunningTimeBasedOnStatsType() {
+ final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
+ // Return the battery time (millisecond) on status mStatsType
+ return mStatsHelper.getStats().computeBatteryRealtime(elapsedRealtimeUs,
+ mStatsType /* STATS_SINCE_CHARGED */) / 1000;
}
@VisibleForTesting
@@ -559,22 +562,15 @@
}
final BatteryMeterView batteryView = (BatteryMeterView) mBatteryLayoutPref
.findViewById(R.id.battery_header_icon);
- final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.time);
+ final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
- final TextView summary2 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary2);
- final int visible = info.remainingTimeUs != 0 ? View.VISIBLE : View.INVISIBLE;
- final int summaryResId = info.mDischarging ?
- R.string.estimated_time_left : R.string.estimated_charging_time_left;
-
- if (info.remainingTimeUs != 0) {
- timeText.setText(Utils.formatElapsedTime(context, info.remainingTimeUs / 1000, false));
+ timeText.setText(Utils.formatPercentage(info.mBatteryLevel));
+ if (info.remainingLabel == null ) {
+ summary1.setText(info.statusLabel);
} else {
- timeText.setText(info.statusLabel);
+ summary1.setText(info.remainingLabel);
}
- summary1.setText(summaryResId);
- summary1.setVisibility(visible);
- summary2.setVisibility(visible);
batteryView.setBatteryInfo(info.mBatteryLevel);
}
diff --git a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
index a6df7a3..a7862ae 100644
--- a/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/AvailableVirtualKeyboardFragment.java
@@ -43,12 +43,11 @@
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodPreference;
import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
import java.text.Collator;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
public final class AvailableVirtualKeyboardFragment extends SettingsPreferenceFragment
@@ -115,7 +114,7 @@
private static Drawable getInputMethodIcon(@NonNull final PackageManager packageManager,
@NonNull final InputMethodInfo imi) {
final ServiceInfo si = imi.getServiceInfo();
- final ApplicationInfo ai = si.applicationInfo;
+ final ApplicationInfo ai = si != null ? si.applicationInfo : null;
final String packageName = imi.getPackageName();
if (si == null || ai == null || packageName == null) {
return new ColorDrawable(Color.TRANSPARENT);
@@ -151,8 +150,8 @@
final Context context = getPrefContext();
final PackageManager packageManager = getActivity().getPackageManager();
final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList();
- final int N = (imis == null ? 0 : imis.size());
- for (int i = 0; i < N; ++i) {
+ final int numImis = (imis == null ? 0 : imis.size());
+ for (int i = 0; i < numImis; ++i) {
final InputMethodInfo imi = imis.get(i);
final boolean isAllowedByOrganization = permittedList == null
|| permittedList.contains(imi.getPackageName());
@@ -162,14 +161,9 @@
mInputMethodPreferenceList.add(pref);
}
final Collator collator = Collator.getInstance();
- Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
- @Override
- public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
- return lhs.compareTo(rhs, collator);
- }
- });
+ mInputMethodPreferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
getPreferenceScreen().removeAll();
- for (int i = 0; i < N; ++i) {
+ for (int i = 0; i < numImis; ++i) {
final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
pref.setOrder(i);
getPreferenceScreen().addPreference(pref);
@@ -190,8 +184,6 @@
static List<SearchIndexableRaw> buildSearchIndexOfInputMethods(final Context context,
final List<InputMethodInfo> inputMethods, final String screenTitle) {
final List<SearchIndexableRaw> indexes = new ArrayList<>();
- final InputMethodManager imm = (InputMethodManager) context.getSystemService(
- Context.INPUT_METHOD_SERVICE);
for (int i = 0; i < inputMethods.size(); i++) {
final InputMethodInfo imi = inputMethods.get(i);
final ServiceInfo serviceInfo = imi.getServiceInfo();
@@ -207,7 +199,7 @@
return indexes;
}
- public static Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
diff --git a/src/com/android/settings/inputmethod/InputMethodPreference.java b/src/com/android/settings/inputmethod/InputMethodPreference.java
deleted file mode 100755
index 463a043..0000000
--- a/src/com/android/settings/inputmethod/InputMethodPreference.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 2011 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.inputmethod;
-
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.os.UserHandle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.Preference.OnPreferenceChangeListener;
-import android.support.v7.preference.Preference.OnPreferenceClickListener;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
-import android.widget.Toast;
-
-import com.android.internal.inputmethod.InputMethodUtils;
-import com.android.settings.R;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
-import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
-import com.android.settingslib.inputmethod.InputMethodSettingValuesWrapper;
-
-import java.text.Collator;
-import java.util.List;
-
-/**
- * Input method preference.
- *
- * This preference represents an IME. It is used for two purposes. 1) An instance with a switch
- * is used to enable or disable the IME. 2) An instance without a switch is used to invoke the
- * setting activity of the IME.
- */
-class InputMethodPreference extends RestrictedSwitchPreference implements OnPreferenceClickListener,
- OnPreferenceChangeListener {
- private static final String TAG = InputMethodPreference.class.getSimpleName();
- private static final String EMPTY_TEXT = "";
- private static final int NO_WIDGET = 0;
-
- interface OnSavePreferenceListener {
- /**
- * Called when this preference needs to be saved its state.
- *
- * Note that this preference is non-persistent and needs explicitly to be saved its state.
- * Because changing one IME state may change other IMEs' state, this is a place to update
- * other IMEs' state as well.
- *
- * @param pref This preference.
- */
- public void onSaveInputMethodPreference(InputMethodPreference pref);
- }
-
- private final InputMethodInfo mImi;
- private final boolean mHasPriorityInSorting;
- private final OnSavePreferenceListener mOnSaveListener;
- private final InputMethodSettingValuesWrapper mInputMethodSettingValues;
- private final boolean mIsAllowedByOrganization;
-
- private AlertDialog mDialog = null;
-
- /**
- * A preference entry of an input method.
- *
- * @param context The Context this is associated with.
- * @param imi The {@link InputMethodInfo} of this preference.
- * @param isImeEnabler true if this preference is the IME enabler that has enable/disable
- * switches for all available IMEs, not the list of enabled IMEs.
- * @param isAllowedByOrganization false if the IME has been disabled by a device or profile
- * owner.
- * @param onSaveListener The listener called when this preference has been changed and needs
- * to save the state to shared preference.
- */
- InputMethodPreference(final Context context, final InputMethodInfo imi,
- final boolean isImeEnabler, final boolean isAllowedByOrganization,
- final OnSavePreferenceListener onSaveListener) {
- super(context);
- setPersistent(false);
- mImi = imi;
- mIsAllowedByOrganization = isAllowedByOrganization;
- mOnSaveListener = onSaveListener;
- if (!isImeEnabler) {
- // Remove switch widget.
- setWidgetLayoutResource(NO_WIDGET);
- }
- // Disable on/off switch texts.
- setSwitchTextOn(EMPTY_TEXT);
- setSwitchTextOff(EMPTY_TEXT);
- setKey(imi.getId());
- setTitle(imi.loadLabel(context.getPackageManager()));
- final String settingsActivity = imi.getSettingsActivity();
- if (TextUtils.isEmpty(settingsActivity)) {
- setIntent(null);
- } else {
- // Set an intent to invoke settings activity of an input method.
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(imi.getPackageName(), settingsActivity);
- setIntent(intent);
- }
- mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(context);
- mHasPriorityInSorting = InputMethodUtils.isSystemIme(imi)
- && mInputMethodSettingValues.isValidSystemNonAuxAsciiCapableIme(imi, context);
- setOnPreferenceClickListener(this);
- setOnPreferenceChangeListener(this);
- }
-
- public InputMethodInfo getInputMethodInfo() {
- return mImi;
- }
-
- private boolean isImeEnabler() {
- // If this {@link SwitchPreference} doesn't have a widget layout, we explicitly hide the
- // switch widget at constructor.
- return getWidgetLayoutResource() != NO_WIDGET;
- }
-
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- // Always returns false to prevent default behavior.
- // See {@link TwoStatePreference#onClick()}.
- if (!isImeEnabler()) {
- // Prevent disabling an IME because this preference is for invoking a settings activity.
- return false;
- }
- if (isChecked()) {
- // Disable this IME.
- setCheckedInternal(false);
- return false;
- }
- if (InputMethodUtils.isSystemIme(mImi)) {
- // Enable a system IME. No need to show a security warning dialog,
- // but we might need to prompt if it's not Direct Boot aware.
- if (mImi.getServiceInfo().directBootAware) {
- setCheckedInternal(true);
- } else {
- showDirectBootWarnDialog();
- }
- } else {
- // Once security is confirmed, we might prompt if the IME isn't
- // Direct Boot aware.
- showSecurityWarnDialog();
- }
- return false;
- }
-
- @Override
- public boolean onPreferenceClick(final Preference preference) {
- // Always returns true to prevent invoking an intent without catching exceptions.
- // See {@link Preference#performClick(PreferenceScreen)}/
- if (isImeEnabler()) {
- // Prevent invoking a settings activity because this preference is for enabling and
- // disabling an input method.
- return true;
- }
- final Context context = getContext();
- try {
- final Intent intent = getIntent();
- if (intent != null) {
- // Invoke a settings activity of an input method.
- context.startActivity(intent);
- }
- } catch (final ActivityNotFoundException e) {
- Log.d(TAG, "IME's Settings Activity Not Found", e);
- final String message = context.getString(
- R.string.failed_to_open_app_settings_toast,
- mImi.loadLabel(context.getPackageManager()));
- Toast.makeText(context, message, Toast.LENGTH_LONG).show();
- }
- return true;
- }
-
- void updatePreferenceViews() {
- final boolean isAlwaysChecked = mInputMethodSettingValues.isAlwaysCheckedIme(
- mImi, getContext());
- // When this preference has a switch and an input method should be always enabled,
- // this preference should be disabled to prevent accidentally disabling an input method.
- // This preference should also be disabled in case the admin does not allow this input
- // method.
- if (isAlwaysChecked && isImeEnabler()) {
- setDisabledByAdmin(null);
- setEnabled(false);
- } else if (!mIsAllowedByOrganization) {
- EnforcedAdmin admin =
- RestrictedLockUtils.checkIfInputMethodDisallowed(getContext(),
- mImi.getPackageName(), UserHandle.myUserId());
- setDisabledByAdmin(admin);
- } else {
- setEnabled(true);
- }
- setChecked(mInputMethodSettingValues.isEnabledImi(mImi));
- if (!isDisabledByAdmin()) {
- setSummary(getSummaryString());
- }
- }
-
- private InputMethodManager getInputMethodManager() {
- return (InputMethodManager)getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- }
-
- private String getSummaryString() {
- final InputMethodManager imm = getInputMethodManager();
- final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(mImi, true);
- return InputMethodAndSubtypeUtil.getSubtypeLocaleNameListAsSentence(
- subtypes, getContext(), mImi);
- }
-
- private void setCheckedInternal(boolean checked) {
- super.setChecked(checked);
- mOnSaveListener.onSaveInputMethodPreference(InputMethodPreference.this);
- notifyChanged();
- }
-
- private void showSecurityWarnDialog() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- final Context context = getContext();
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setCancelable(true /* cancelable */);
- builder.setTitle(android.R.string.dialog_alert_title);
- final CharSequence label = mImi.getServiceInfo().applicationInfo.loadLabel(
- context.getPackageManager());
- builder.setMessage(context.getString(R.string.ime_security_warning, label));
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- // The user confirmed to enable a 3rd party IME, but we might
- // need to prompt if it's not Direct Boot aware.
- if (mImi.getServiceInfo().directBootAware) {
- setCheckedInternal(true);
- } else {
- showDirectBootWarnDialog();
- }
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- // The user canceled to enable a 3rd party IME.
- setCheckedInternal(false);
- }
- });
- mDialog = builder.create();
- mDialog.show();
- }
-
- private void showDirectBootWarnDialog() {
- if (mDialog != null && mDialog.isShowing()) {
- mDialog.dismiss();
- }
- final Context context = getContext();
- final AlertDialog.Builder builder = new AlertDialog.Builder(context);
- builder.setCancelable(true /* cancelable */);
- builder.setMessage(context.getText(R.string.direct_boot_unaware_dialog_message));
- builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- setCheckedInternal(true);
- }
- });
- builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(final DialogInterface dialog, final int which) {
- setCheckedInternal(false);
- }
- });
- mDialog = builder.create();
- mDialog.show();
- }
-
- int compareTo(final InputMethodPreference rhs, final Collator collator) {
- if (this == rhs) {
- return 0;
- }
- if (mHasPriorityInSorting == rhs.mHasPriorityInSorting) {
- final CharSequence t0 = getTitle();
- final CharSequence t1 = rhs.getTitle();
- if (TextUtils.isEmpty(t0)) {
- return 1;
- }
- if (TextUtils.isEmpty(t1)) {
- return -1;
- }
- return collator.compare(t0.toString(), t1.toString());
- }
- // Prefer always checked system IMEs
- return mHasPriorityInSorting ? -1 : 1;
- }
-}
diff --git a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
index c362389..7b7c599 100644
--- a/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
+++ b/src/com/android/settings/inputmethod/VirtualKeyboardFragment.java
@@ -35,6 +35,7 @@
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.inputmethod.InputMethodAndSubtypeUtil;
+import com.android.settingslib.inputmethod.InputMethodPreference;
import java.text.Collator;
import java.util.ArrayList;
@@ -104,12 +105,7 @@
mInputMethodPreferenceList.add(pref);
}
final Collator collator = Collator.getInstance();
- Collections.sort(mInputMethodPreferenceList, new Comparator<InputMethodPreference>() {
- @Override
- public int compare(InputMethodPreference lhs, InputMethodPreference rhs) {
- return lhs.compareTo(rhs, collator);
- }
- });
+ mInputMethodPreferenceList.sort((lhs, rhs) -> lhs.compareTo(rhs, collator));
getPreferenceScreen().removeAll();
for (int i = 0; i < N; ++i) {
final InputMethodPreference pref = mInputMethodPreferenceList.get(i);
diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
index 07495ee..1a60256 100644
--- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
+++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java
@@ -66,6 +66,18 @@
}
};
+ private final WifiManager.ActionListener mForgetListener = new WifiManager.ActionListener() {
+ @Override
+ public void onSuccess() {
+ initPreferences();
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ initPreferences();
+ }
+ };
+
private WifiDialog mDialog;
private WifiManager mWifiManager;
private AccessPoint mDlgAccessPoint;
@@ -229,11 +241,12 @@
Log.e(TAG, "Failed to remove Passpoint configuration for "
+ mSelectedAccessPoint.getConfigName());
}
+ initPreferences();
} else {
- mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, null);
+ // mForgetListener will call initPreferences upon completion
+ mWifiManager.forget(mSelectedAccessPoint.getConfig().networkId, mForgetListener);
}
mSelectedAccessPoint = null;
- initPreferences();
}
}
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index e5c21ff..38f5a43 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -516,7 +516,10 @@
if (mSelectedAccessPoint.isActive()) {
return super.onPreferenceTreeClick(preference);
}
- /** Bypass dialog and connect to unsecured or previously connected saved networks. */
+ /**
+ * Bypass dialog and connect to unsecured networks, or previously connected saved
+ * networks, or Passpoint provided networks.
+ */
WifiConfiguration config = mSelectedAccessPoint.getConfig();
if (mSelectedAccessPoint.getSecurity() == AccessPoint.SECURITY_NONE) {
mSelectedAccessPoint.generateOpenNetworkConfig();
@@ -525,6 +528,10 @@
&& config.getNetworkSelectionStatus() != null
&& config.getNetworkSelectionStatus().getHasEverConnected()) {
connect(config, true /* isSavedNetwork */);
+ } else if (mSelectedAccessPoint.isPasspoint()) {
+ // Access point provided by an installed Passpoint provider, connect using
+ // the associated config.
+ connect(config, true /* isSavedNetwork */);
} else {
showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
}
diff --git a/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java b/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java
new file mode 100644
index 0000000..11a49fc
--- /dev/null
+++ b/tests/app/src/com/android/settings/wifi/WifiSettingsUiTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.wifi;
+
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.R;
+import com.android.settings.Settings.WifiSettingsActivity;
+import com.android.settingslib.wifi.WifiTracker;
+import com.android.settingslib.wifi.WifiTrackerFactory;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class WifiSettingsUiTest {
+
+ // TODO(sghuman): Investigate why resource ids are not resolving correctly in the test apk,
+ // then remove this manual string entry
+ private static final String WIFI_PREFERENCES = "Wi\\u2011Fi preferences";
+
+ @Mock private WifiTracker mockWifiTracker;
+
+ @Rule
+ public ActivityTestRule<WifiSettingsActivity> mActivityRule =
+ new ActivityTestRule<>(WifiSettingsActivity.class, true);
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ WifiTrackerFactory.setTestingWifiTracker(mockWifiTracker);
+ }
+
+ private void launchActivity() {
+ mActivityRule.launchActivity(new Intent("android.settings.WIFI_SETTINGS"));
+ }
+
+ @Test
+ public void launchActivityShouldSucceed() {
+ launchActivity();
+ }
+
+ @Test
+ public void shouldShowWifiPreferences() {
+ launchActivity();
+ onView(withText(WIFI_PREFERENCES)).perform(click());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index 3d4b840..a33a8c8 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -23,12 +23,16 @@
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.os.BatteryStats;
import android.os.UserManager;
import android.support.v7.preference.Preference;
import android.view.View;
import android.widget.Button;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.instantapps.InstantAppButtonsController;
@@ -53,8 +57,10 @@
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -64,23 +70,37 @@
public final class InstalledAppDetailsTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
-
@Mock
ApplicationFeatureProvider mApplicationFeatureProvider;
-
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private UserManager mUserManager;
@Mock
- private Activity mActivity;
+ private SettingsActivity mActivity;
@Mock
private DevicePolicyManager mDevicePolicyManager;
+ @Mock
+ private Preference mBatteryPreference;
+ @Mock
+ private BatterySipper mBatterySipper;
+ @Mock
+ private BatteryStatsHelper mBatteryStatsHelper;
+ @Mock
+ private BatteryStats.Uid mUid;
private InstalledAppDetails mAppDetail;
+ private Context mShadowContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mAppDetail = new InstalledAppDetails();
+ mShadowContext = RuntimeEnvironment.application;
+
+ mAppDetail = spy(new InstalledAppDetails());
+
+ mBatterySipper.drainType = BatterySipper.DrainType.IDLE;
+ mBatterySipper.uidObj = mUid;
+ doReturn(mActivity).when(mAppDetail).getActivity();
+ doReturn(mShadowContext).when(mAppDetail).getContext();
// Default to not considering any apps to be instant (individual tests can override this).
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
@@ -127,7 +147,7 @@
when(stats.getTotalBytes()).thenReturn(1L);
assertThat(InstalledAppDetails.getStorageSummary(context, stats, true))
- .isEqualTo("1.00B used in External storage");
+ .isEqualTo("1.00B used in external storage");
}
@Test
@@ -137,7 +157,7 @@
when(stats.getTotalBytes()).thenReturn(1L);
assertThat(InstalledAppDetails.getStorageSummary(context, stats, false))
- .isEqualTo("1.00B used in Internal storage");
+ .isEqualTo("1.00B used in internal storage");
}
@Test
@@ -157,6 +177,16 @@
verify(mActivity, never()).finishAndRemoveTask();
}
+ @Test
+ public void launchPowerUsageDetailFragment_shouldNotCrash() {
+ mAppDetail.mBatteryPreference = mBatteryPreference;
+ mAppDetail.mSipper = mBatterySipper;
+ mAppDetail.mBatteryHelper = mBatteryStatsHelper;
+
+ // Should not crash
+ mAppDetail.onPreferenceClick(mBatteryPreference);
+ }
+
// Tests that we don't show the "uninstall for all users" button for instant apps.
@Test
public void instantApps_noUninstallForAllButton() {
@@ -184,7 +214,7 @@
public void instantApps_noUninstallButton() {
// Make this app appear to be instant.
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
- (InstantAppDataProvider) (i -> true));
+ (InstantAppDataProvider) (i -> true));
final ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_INSTALLED;
info.enabled = true;
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
index 84d3b98..95f9fbe 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/StorageSettingsTest.java
@@ -18,6 +18,7 @@
import android.app.Activity;
+import android.app.usage.StorageStatsManager;
import android.icu.text.NumberFormat;
import android.os.storage.VolumeInfo;
import android.text.format.Formatter;
@@ -40,6 +41,7 @@
import java.util.ArrayList;
import java.util.List;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -73,9 +75,14 @@
final SummaryLoader.SummaryProvider provider =
StorageSettings.SUMMARY_PROVIDER_FACTORY.createSummaryProvider(mActivity, loader);
final VolumeInfo volumeInfo = mVolumes.get(0);
+ when(volumeInfo.isMountedReadable()).thenReturn(true);
when(volumeInfo.getType()).thenReturn(VolumeInfo.TYPE_PRIVATE);
- when(volumeInfo.getPath().getTotalSpace()).thenReturn(500L);
- when(volumeInfo.getPath().getFreeSpace()).thenReturn(0L);
+ when(mStorageManagerVolumeProvider.getTotalBytes(
+ any(StorageStatsManager.class), any(VolumeInfo.class)))
+ .thenReturn(500L);
+ when(mStorageManagerVolumeProvider.getFreeBytes(
+ any(StorageStatsManager.class), any(VolumeInfo.class)))
+ .thenReturn(0L);
ReflectionHelpers.setField(
provider, "mStorageManagerVolumeProvider", mStorageManagerVolumeProvider);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index a6e0943..5f2d54f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -15,19 +15,17 @@
*/
package com.android.settings.fuelgauge;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.os.Process;
-import android.support.v7.preference.Preference;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
import android.widget.TextView;
+
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -40,6 +38,7 @@
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.BatteryInfo;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -53,13 +52,15 @@
import java.util.ArrayList;
import java.util.List;
-import static com.android.settings.fuelgauge.PowerUsageBase.MENU_STATS_REFRESH;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADDITIONAL_BATTERY_INFO;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -77,9 +78,13 @@
public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
private static final String TIME_LEFT = "2h30min";
+ private static final int BATTERY_LEVEL = 55;
private static final int UID = 123;
private static final int POWER_MAH = 100;
private static final long REMAINING_TIME_US = 100000;
+ private static final long TIME_SINCE_LAST_FULL_CHARGE_MS = 25000;
+ private static final long TIME_SINCE_LAST_FULL_CHARGE_US =
+ TIME_SINCE_LAST_FULL_CHARGE_MS * 1000;
private static final int DISCHARGE_AMOUNT = 100;
private static final long USAGE_TIME_MS = 10000;
private static final double TOTAL_POWER = 200;
@@ -117,20 +122,16 @@
@Mock
private BatteryMeterView mBatteryMeterView;
@Mock
- private TextView mTimeText;
+ private TextView mBatteryPercentText;
@Mock
private TextView mSummary1;
@Mock
- private TextView mSummary2;
- @Mock
private BatteryInfo mBatteryInfo;
@Mock
- private Preference mScreenUsagePref;
+ private PowerGaugePreference mScreenUsagePref;
@Mock
- private Preference mScreenConsumptionPref;
- @Mock
- private Preference mCellularNetworkPref;
- @Mock
+ private PowerGaugePreference mLastFullChargePref;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStatsHelper mBatteryHelper;
@Mock
private PowerManager mPowerManager;
@@ -153,7 +154,7 @@
mFragment = spy(new TestFragment(mContext));
mFragment.initFeatureProvider();
-
+
when(mFragment.getActivity()).thenReturn(mSettingsActivity);
when(mAdditionalBatteryInfoMenu.getItemId())
.thenReturn(MENU_ADDITIONAL_BATTERY_INFO);
@@ -162,6 +163,8 @@
when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
.thenReturn(ADDITIONAL_BATTERY_INFO_INTENT);
when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER);
+ when(mBatteryHelper.getStats().computeBatteryRealtime(anyLong(), anyInt())).thenReturn(
+ TIME_SINCE_LAST_FULL_CHARGE_US);
when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
when(mNormalBatterySipper.getUid()).thenReturn(UID);
@@ -172,8 +175,7 @@
mCellBatterySipper.totalPowerMah = POWER_MAH;
when(mBatteryLayoutPref.findViewById(R.id.summary1)).thenReturn(mSummary1);
- when(mBatteryLayoutPref.findViewById(R.id.summary2)).thenReturn(mSummary2);
- when(mBatteryLayoutPref.findViewById(R.id.time)).thenReturn(mTimeText);
+ when(mBatteryLayoutPref.findViewById(R.id.battery_percent)).thenReturn(mBatteryPercentText);
when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
.thenReturn(mBatteryMeterView);
mFragment.setBatteryLayoutPreference(mBatteryLayoutPref);
@@ -194,8 +196,9 @@
mFragment.mStatsHelper = mBatteryHelper;
when(mBatteryHelper.getUsageList()).thenReturn(mUsageList);
mFragment.mScreenUsagePref = mScreenUsagePref;
- mFragment.mScreenConsumptionPref = mScreenConsumptionPref;
- mFragment.mCellularNetworkPref = mCellularNetworkPref;
+ mFragment.mLastFullChargePref = mLastFullChargePref;
+
+ mBatteryInfo.mBatteryLevel = BATTERY_LEVEL;
}
@Test
@@ -226,7 +229,7 @@
}
@Test
- public void testOptionsMenu_MenuHighPower_MetricEventInvoked() {
+ public void testOptionsMenu_menuHighPower_metricEventInvoked() {
mFragment.onOptionsItemSelected(mHighPowerMenu);
verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
@@ -234,7 +237,7 @@
}
@Test
- public void testOptionsMenu_MenuAdditionalBattery_MetricEventInvoked() {
+ public void testOptionsMenu_menuAdditionalBattery_metricEventInvoked() {
mFragment.onOptionsItemSelected(mAdditionalBatteryInfoMenu);
verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
@@ -242,7 +245,7 @@
}
@Test
- public void testOptionsMenu_MenuAppToggle_MetricEventInvoked() {
+ public void testOptionsMenu_menuAppToggle_metricEventInvoked() {
mFragment.onOptionsItemSelected(mToggleAppsMenu);
mFragment.mShowAllApps = false;
@@ -251,7 +254,7 @@
}
@Test
- public void testOptionsMenu_ToggleAppsEnabled() {
+ public void testOptionsMenu_toggleAppsEnabled() {
when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
.thenReturn(true);
mFragment.mShowAllApps = false;
@@ -262,13 +265,13 @@
}
@Test
- public void testOptionsMenu_ClickToggleAppsMenu_DataChanged() {
+ public void testOptionsMenu_clickToggleAppsMenu_dataChanged() {
testToggleAllApps(true);
testToggleAllApps(false);
}
@Test
- public void testExtractKeyFromSipper_TypeAPPUidObjectNull_ReturnPackageNames() {
+ public void testExtractKeyFromSipper_typeAPPUidObjectNull_returnPackageNames() {
mNormalBatterySipper.uidObj = null;
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
@@ -277,7 +280,7 @@
}
@Test
- public void testExtractKeyFromSipper_TypeOther_ReturnDrainType() {
+ public void testExtractKeyFromSipper_typeOther_returnDrainType() {
mNormalBatterySipper.uidObj = null;
mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
@@ -286,7 +289,7 @@
}
@Test
- public void testExtractKeyFromSipper_TypeAPPUidObjectNotNull_ReturnUid() {
+ public void testExtractKeyFromSipper_typeAPPUidObjectNotNull_returnUid() {
mNormalBatterySipper.uidObj = new BatteryStatsImpl.Uid(new BatteryStatsImpl(), UID);
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
@@ -295,7 +298,7 @@
}
@Test
- public void testRemoveHiddenBatterySippers_ContainsHiddenSippers_RemoveAndReturnValue() {
+ public void testRemoveHiddenBatterySippers_containsHiddenSippers_removeAndReturnValue() {
final List<BatterySipper> sippers = new ArrayList<>();
sippers.add(mNormalBatterySipper);
sippers.add(mScreenBatterySipper);
@@ -309,37 +312,37 @@
}
@Test
- public void testShouldHideSipper_TypeIdle_ReturnTrue() {
+ public void testShouldHideSipper_typeIdle_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.IDLE;
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
}
@Test
- public void testShouldHideSipper_TypeWifi_ReturnTrue() {
+ public void testShouldHideSipper_typeWifi_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.WIFI;
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
}
@Test
- public void testShouldHideSipper_TypeCell_ReturnTrue() {
+ public void testShouldHideSipper_typeCell_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
}
@Test
- public void testShouldHideSipper_TypeScreen_ReturnTrue() {
+ public void testShouldHideSipper_typeScreen_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
}
@Test
- public void testShouldHideSipper_TypeBluetooth_ReturnTrue() {
+ public void testShouldHideSipper_typeBluetooth_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
}
@Test
- public void testShouldHideSipper_TypeSystem_ReturnTrue() {
+ public void testShouldHideSipper_typeSystem_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
when(mFeatureFactory.powerUsageFeatureProvider.isTypeSystem(Matchers.<BatterySipper>any()))
@@ -348,14 +351,14 @@
}
@Test
- public void testShouldHideSipper_UidNormal_ReturnFalse() {
+ public void testShouldHideSipper_uidNormal_returnFalse() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
when(mNormalBatterySipper.getUid()).thenReturn(UID);
assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isFalse();
}
@Test
- public void testShouldHideSipper_TypeService_ReturnTrue() {
+ public void testShouldHideSipper_typeService_returnTrue() {
mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
when(mNormalBatterySipper.getUid()).thenReturn(UID);
when(mFeatureFactory.powerUsageFeatureProvider.isTypeService(Matchers.<BatterySipper>any()))
@@ -365,7 +368,7 @@
}
@Test
- public void testSetUsageSummary_TimeLessThanOneMinute_DoNotSetSummary() {
+ public void testSetUsageSummary_timeLessThanOneMinute_doNotSetSummary() {
final long usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS;
mFragment.setUsageSummary(mPreference, "", usageTimeMs);
@@ -373,7 +376,7 @@
}
@Test
- public void testSetUsageSummary_TimeMoreThanOneMinute_SetSummary() {
+ public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() {
final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
mFragment.setUsageSummary(mPreference, "", usageTimeMs);
@@ -381,45 +384,25 @@
}
@Test
- public void testUpdatePreference_NoEstimatedTime_DoNotShowSummary() {
- mBatteryInfo.remainingTimeUs = 0;
+ public void testUpdatePreference_hasRemainingTime_showRemainingLabel() {
mBatteryInfo.remainingLabel = TIME_LEFT;
+
mFragment.updateHeaderPreference(mBatteryInfo);
- verify(mSummary1).setVisibility(View.INVISIBLE);
- verify(mSummary2).setVisibility(View.INVISIBLE);
+ verify(mSummary1).setText(mBatteryInfo.remainingLabel);
}
@Test
- public void testUpdatePreference_HasEstimatedTime_ShowSummary() {
- mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
- mBatteryInfo.remainingLabel = TIME_LEFT;
+ public void testUpdatePreference_noRemainingTime_showStatusLabel() {
+ mBatteryInfo.remainingLabel = null;
+
mFragment.updateHeaderPreference(mBatteryInfo);
- verify(mSummary1).setVisibility(View.VISIBLE);
- verify(mSummary2).setVisibility(View.VISIBLE);
+ verify(mSummary1).setText(mBatteryInfo.statusLabel);
}
@Test
- public void testUpdatePreference_Charging_ShowChargingTimeLeft() {
- mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
- mBatteryInfo.mDischarging = false;
-
- mFragment.updateHeaderPreference(mBatteryInfo);
- verify(mSummary1).setText(R.string.estimated_charging_time_left);
- }
-
- @Test
- public void testUpdatePreference_NotCharging_ShowTimeLeft() {
- mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
- mBatteryInfo.mDischarging = true;
-
- mFragment.updateHeaderPreference(mBatteryInfo);
- verify(mSummary1).setText(R.string.estimated_time_left);
- }
-
- @Test
- public void testUpdateHeaderPreference_AsyncUpdate_ShouldNotCrash() {
+ public void testUpdateHeaderPreference_asyncUpdate_shouldNotCrash() {
when(mFragment.getContext()).thenReturn(null);
mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
@@ -451,43 +434,36 @@
}
@Test
- public void testUpdateCellularPreference_ShowCorrectSummary() {
- final double percent = POWER_MAH / TOTAL_POWER * DISCHARGE_AMOUNT;
- final String expectedSummary = mRealContext.getString(R.string.battery_overall_usage,
- Utils.formatPercentage((int) percent));
- doReturn(expectedSummary).when(mFragment)
- .getString(eq(R.string.battery_overall_usage), anyInt());
- mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
+ public void testUpdateScreenPreference_showCorrectSummary() {
+ final String expectedUsedTime = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, false);
+ doReturn(mScreenBatterySipper).when(mFragment).findBatterySipperByType(any(), any());
+ doReturn(mRealContext).when(mFragment).getContext();
- verify(mCellularNetworkPref).setSummary(expectedSummary);
+ mFragment.updateScreenPreference();
+
+ verify(mScreenUsagePref).setSubtitle(expectedUsedTime);
}
@Test
- public void testUpdateScreenPreference_ShowCorrectSummary() {
- final String expectedUsedTime = mRealContext.getString(R.string.battery_used_for,
- Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS, false));
- final double percent = BATTERY_SCREEN_USAGE / TOTAL_POWER * DISCHARGE_AMOUNT;
- final String expectedOverallUsage = mRealContext.getString(R.string.battery_overall_usage,
- Utils.formatPercentage((int) percent));
- doReturn(expectedUsedTime).when(mFragment).getString(
- eq(R.string.battery_used_for), anyInt());
- doReturn(expectedOverallUsage).when(mFragment).getString(
- eq(R.string.battery_overall_usage), anyInt());
+ public void testUpdateLastFullChargePreference_showCorrectSummary() {
+ doReturn(mRealContext).when(mFragment).getContext();
+ final String expected = mRealContext.getString(R.string.power_last_full_charge_summary,
+ Utils.formatElapsedTime(mRealContext, TIME_SINCE_LAST_FULL_CHARGE_MS, false));
+ doReturn(expected).when(mFragment).getString(eq(R.string.power_last_full_charge_summary),
+ any());
- mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
+ mFragment.updateLastFullChargePreference(TIME_SINCE_LAST_FULL_CHARGE_MS);
- verify(mScreenUsagePref).setSummary(expectedUsedTime);
- verify(mScreenConsumptionPref).setSummary(expectedOverallUsage);
+ verify(mLastFullChargePref).setSubtitle(expected);
}
@Test
- public void testUpdatePreference_UsageListEmpty_ShouldNotCrash() {
+ public void testUpdatePreference_usageListEmpty_shouldNotCrash() {
when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList<BatterySipper>());
- doReturn("").when(mFragment).getString(anyInt(), Matchers.anyObject());
+ doReturn("").when(mFragment).getString(anyInt(), any());
// Should not crash when update
- mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
- mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
+ mFragment.updateScreenPreference();
}
@Test
@@ -496,6 +472,12 @@
assertThat(percent).isWithin(PRECISION).of(POWER_USAGE_PERCENTAGE);
}
+ @Test
+ public void testCalculateRunningTimeBasedOnStatsType() {
+ assertThat(mFragment.calculateRunningTimeBasedOnStatsType()).isEqualTo(
+ TIME_SINCE_LAST_FULL_CHARGE_MS);
+ }
+
public static class TestFragment extends PowerUsageSummary {
private Context mContext;