Merge "Turn off QUIET_MODE before changing unified lock credential." into oc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8535b2f..2d8e06a 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3077,6 +3077,16 @@
android:permission="android.permission.DUMP"
android:enabled="@bool/config_has_help" />
+ <activity android:name=".applications.defaultapps.AutofillPickerActivity"
+ android:taskAffinity=""
+ android:noHistory="true">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.REQUEST_SET_AUTOFILL_SERVICE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:scheme="package" />
+ </intent-filter>
+ </activity>
+
<!-- This is the longest AndroidManifest.xml ever. -->
</application>
</manifest>
diff --git a/res/layout/app_details.xml b/res/layout/app_details.xml
index b05c0dc..c3ffe1a 100644
--- a/res/layout/app_details.xml
+++ b/res/layout/app_details.xml
@@ -112,9 +112,4 @@
</RelativeLayout>
- <!-- Drop shadow -->
- <View android:layout_width="match_parent"
- android:layout_height="5dp"
- android:background="@drawable/action_bar_dropshadow"/>
-
</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/battery_header.xml b/res/layout/battery_header.xml
index 04ef74d..97cc016 100644
--- a/res/layout/battery_header.xml
+++ b/res/layout/battery_header.xml
@@ -46,8 +46,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
- android:textAppearance="@android:style/TextAppearance.Material.Small"
- android:text="@string/estimated_time_left"/>
+ android:textAppearance="@android:style/TextAppearance.Material.Small"/>
</LinearLayout>
diff --git a/res/layout/connection_detail_pref.xml b/res/layout/connection_detail_pref.xml
index 15f1c77..182f2cb 100644
--- a/res/layout/connection_detail_pref.xml
+++ b/res/layout/connection_detail_pref.xml
@@ -43,6 +43,7 @@
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:singleLine="false"
android:paddingLeft="20dp"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textColor="@android:color/white"/>
diff --git a/res/layout/search_breadcrumb_view.xml b/res/layout/search_breadcrumb_view.xml
index a78b745..08a2651 100644
--- a/res/layout/search_breadcrumb_view.xml
+++ b/res/layout/search_breadcrumb_view.xml
@@ -20,7 +20,7 @@
android:id="@+id/breadcrumb"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingTop="8dp"
+ android:paddingTop="5dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
- android:ellipsize="marquee"/>
\ No newline at end of file
+ android:ellipsize="marquee"/>
diff --git a/res/layout/search_inline_switch_item.xml b/res/layout/search_inline_switch_item.xml
index 75943c4..526f9fd 100644
--- a/res/layout/search_inline_switch_item.xml
+++ b/res/layout/search_inline_switch_item.xml
@@ -46,9 +46,8 @@
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceListItemSecondary"
- android:textColor="?android:attr/textColorSecondary"
- android:maxLines="10"/>
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceListItemSecondary"/>
<include layout="@layout/search_breadcrumb_view"/>
</LinearLayout>
diff --git a/res/layout/search_intent_item.xml b/res/layout/search_intent_item.xml
index 31f7f26..98e2a9b 100644
--- a/res/layout/search_intent_item.xml
+++ b/res/layout/search_intent_item.xml
@@ -46,9 +46,8 @@
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
- android:textColor="?android:attr/textColorSecondary"
- android:maxLines="3"
android:ellipsize="marquee"/>
<include layout="@layout/search_breadcrumb_view"/>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index adbc1d6..b255123 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4474,10 +4474,10 @@
<!-- Title for the cellular network in power use UI(i.e. Mobile network scanning: 30% of battery usage) [CHAR_LIMIT=40] -->
<string name="device_cellular_network">Mobile network scanning</string>
- <!-- Label for time since last full charge in power use UI, i.e. "7 h 20 min ago" [CHAR_LIMIT=60] -->
- <string name="power_last_full_charge_summary"><xliff:g id="time">%1$s</xliff:g> ago</string>
- <!-- Label for list of apps using battery in power use UI [CHAR_LIMIT=120] -->
- <string name="power_usage_list_summary">App usage since full charge (<xliff:g id="time">%1$s</xliff:g> ago)</string>
+ <!-- Label for time since last full charge in power use UI, i.e. "7 h 20 min ago". Note: ^1 should be used in all translations [CHAR_LIMIT=60] -->
+ <string name="power_last_full_charge_summary"><xliff:g id="time">^1</xliff:g> ago</string>
+ <!-- Label for list of apps using battery in power use UI. Note: ^1 should be used in all translations[CHAR_LIMIT=120] -->
+ <string name="power_usage_list_summary">App usage since full charge (<xliff:g id="time">^1</xliff:g> ago)</string>
<!-- Description for the screen usage item [CHAR_LIMIT=120] -->
<string name="screen_usage_summary">Amount of time screen has been on since full charge</string>
<!-- Label for list of different types using battery in power use UI [CHAR_LIMIT=60] -->
@@ -4676,8 +4676,8 @@
<!-- Representation of a mAh value. [CHAR LIMIT=NONE] -->
<string name="mah"><xliff:g id="number" example="30">%d</xliff:g> mAh</string>
- <!-- Description for battery usage time for an app, i.e. Used for 30min. [CHAR LIMIT=60] -->
- <string name="battery_used_for">Used for %1$s</string>
+ <!-- Description for battery usage time for an app, i.e. Used for 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
+ <string name="battery_used_for">Used for <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
<string name="battery_used_by"><xliff:g id="percent">%1$s</xliff:g> used by <xliff:g id="app">%2$s</xliff:g></string>
<!-- Description for percentage of battery usage for an app, i.e. Screen: 30% of overall battery. [CHAR LIMIT=60] -->
diff --git a/src/com/android/settings/ApnEditor.java b/src/com/android/settings/ApnEditor.java
index f97811c..f668957 100644
--- a/src/com/android/settings/ApnEditor.java
+++ b/src/com/android/settings/ApnEditor.java
@@ -788,9 +788,14 @@
* Check the key fields' validity and save if valid.
* @param force save even if the fields are not valid, if the app is
* being suspended
- * @return true if the data was saved
+ * @return true if there's no error
*/
private boolean validateAndSave(boolean force) {
+ // nothing to do if it's a read only APN
+ if (mReadOnlyApn) {
+ return true;
+ }
+
String name = checkNotSet(mName.getText());
String apn = checkNotSet(mApn.getText());
String mcc = checkNotSet(mMcc.getText());
diff --git a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
index a2e9fe9..2c97e1a 100644
--- a/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/ConfirmDeviceCredentialBaseFragment.java
@@ -68,8 +68,6 @@
PACKAGE + ".ConfirmCredentials.showWhenLocked";
private FingerprintUiHelper mFingerprintHelper;
- protected boolean mIsStrongAuthRequired;
- private boolean mAllowFpAuthentication;
protected boolean mReturnCredentials = false;
protected Button mCancelButton;
protected ImageView mFingerprintIcon;
@@ -83,8 +81,6 @@
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
- ALLOW_FP_AUTHENTICATION, false);
mReturnCredentials = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_RETURN_CREDENTIALS, false);
// Only take this argument into account if it belongs to the current profile.
@@ -133,23 +129,26 @@
// credential. Otherwise, fingerprint can't unlock fbe/keystore through
// verifyTiedProfileChallenge. In such case, we also wanna show the user message that
// fingerprint is disabled due to device restart.
- private boolean isFingerprintDisallowedByStrongAuth() {
+ protected boolean isFingerprintDisallowedByStrongAuth() {
return !(mLockPatternUtils.isFingerprintAllowedForUser(mEffectiveUserId)
&& mUserManager.isUserUnlocked(mUserId));
}
+ private boolean isFingerprintAllowed() {
+ return !mReturnCredentials
+ && getActivity().getIntent().getBooleanExtra(ALLOW_FP_AUTHENTICATION, false)
+ && !isFingerprintDisallowedByStrongAuth()
+ && !isFingerprintDisabledByAdmin();
+ }
+
@Override
public void onResume() {
super.onResume();
- mIsStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
- mAllowFpAuthentication = getActivity().getIntent().getBooleanExtra(
- ALLOW_FP_AUTHENTICATION, false)
- && !isFingerprintDisabledByAdmin() && !mReturnCredentials && !mIsStrongAuthRequired;
refreshLockScreen();
}
protected void refreshLockScreen() {
- if (mAllowFpAuthentication) {
+ if (isFingerprintAllowed()) {
mFingerprintHelper.startListening();
} else {
if (mFingerprintHelper.isListening()) {
diff --git a/src/com/android/settings/ConfirmLockPassword.java b/src/com/android/settings/ConfirmLockPassword.java
index 5c86dcd..9a285f2 100644
--- a/src/com/android/settings/ConfirmLockPassword.java
+++ b/src/com/android/settings/ConfirmLockPassword.java
@@ -191,9 +191,10 @@
}
private int getDefaultDetails() {
+ boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
boolean isProfile = UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId);
// Map boolean flags to an index by isStrongAuth << 2 + isProfile << 1 + isAlpha.
- int index = ((mIsStrongAuthRequired ? 1 : 0) << 2) + ((isProfile ? 1 : 0) << 1)
+ int index = ((isStrongAuthRequired ? 1 : 0) << 2) + ((isProfile ? 1 : 0) << 1)
+ (mIsAlpha ? 1 : 0);
return DETAIL_TEXTS[index];
}
@@ -443,6 +444,7 @@
checkForPendingIntent();
} else {
if (timeoutMs > 0) {
+ refreshLockScreen();
long deadline = mLockPatternUtils.setLockoutAttemptDeadline(
effectiveUserId, timeoutMs);
handleAttemptLockout(deadline);
diff --git a/src/com/android/settings/ConfirmLockPattern.java b/src/com/android/settings/ConfirmLockPattern.java
index 4b65163..56d92f1 100644
--- a/src/com/android/settings/ConfirmLockPattern.java
+++ b/src/com/android/settings/ConfirmLockPattern.java
@@ -236,12 +236,13 @@
}
private int getDefaultDetails() {
+ boolean isStrongAuthRequired = isFingerprintDisallowedByStrongAuth();
if (UserManager.get(getActivity()).isManagedProfile(mEffectiveUserId)) {
- return mIsStrongAuthRequired
+ return isStrongAuthRequired
? R.string.lockpassword_strong_auth_required_reason_restart_work_pattern
: R.string.lockpassword_confirm_your_pattern_generic_profile;
} else {
- return mIsStrongAuthRequired
+ return isStrongAuthRequired
? R.string.lockpassword_strong_auth_required_reason_restart_device_pattern
: R.string.lockpassword_confirm_your_pattern_generic;
}
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index fa9410d..69f563e 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -284,11 +284,13 @@
.getAuthenticatorTypesAsUser(profileId);
final int M = descs.length;
- View titleView = Utils.inflateCategoryHeader(inflater, contents);
- final TextView titleText = (TextView) titleView.findViewById(android.R.id.title);
- titleText.setText(userInfo.isManagedProfile() ? R.string.category_work
- : R.string.category_personal);
- contents.addView(titleView);
+ if (profilesSize > 1) {
+ View titleView = Utils.inflateCategoryHeader(inflater, contents);
+ final TextView titleText = (TextView) titleView.findViewById(android.R.id.title);
+ titleText.setText(userInfo.isManagedProfile() ? R.string.category_work
+ : R.string.category_personal);
+ contents.addView(titleView);
+ }
for (int i = 0; i < N; i++) {
Account account = accounts[i];
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index d04ae8d..f6f980a 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -81,6 +81,8 @@
import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.TtsSpan;
@@ -770,8 +772,9 @@
* @param withSeconds include seconds?
* @return the formatted elapsed time
*/
- public static String formatElapsedTime(Context context, double millis, boolean withSeconds) {
- StringBuilder sb = new StringBuilder();
+ public static CharSequence formatElapsedTime(Context context, double millis,
+ boolean withSeconds) {
+ SpannableStringBuilder sb = new SpannableStringBuilder();
int seconds = (int) Math.floor(millis / 1000);
if (!withSeconds) {
// Round up.
@@ -812,9 +815,15 @@
hours, minutes));
} else {
sb.append(context.getString(R.string.battery_history_minutes_no_seconds, minutes));
+
+ // Add ttsSpan if it only have minute value, because it will be read as "meters"
+ TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(minutes)
+ .setUnit("minute").build();
+ sb.setSpan(ttsSpan, 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
- return sb.toString();
+
+ return sb;
}
/**
@@ -1256,4 +1265,5 @@
return (volume != null) && (volume.getType() == VolumeInfo.TYPE_PRIVATE)
&& volume.isMountedReadable();
}
+
}
diff --git a/src/com/android/settings/accounts/AccountPreferenceBase.java b/src/com/android/settings/accounts/AccountPreferenceBase.java
index 2ad21d9..7c3b54c 100644
--- a/src/com/android/settings/accounts/AccountPreferenceBase.java
+++ b/src/com/android/settings/accounts/AccountPreferenceBase.java
@@ -17,14 +17,10 @@
package com.android.settings.accounts;
-import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SyncStatusObserver;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
@@ -32,12 +28,10 @@
import android.os.UserManager;
import android.support.v7.preference.PreferenceScreen;
import android.text.format.DateFormat;
-import android.text.format.DateUtils;
import android.util.Log;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
-import com.android.settings.utils.LocalClassLoaderContextThemeWrapper;
import com.android.settingslib.accounts.AuthenticatorHelper;
import java.util.ArrayList;
diff --git a/src/com/android/settings/accounts/AccountSyncPreferenceController.java b/src/com/android/settings/accounts/AccountSyncPreferenceController.java
index 57d317b..0b095f7 100644
--- a/src/com/android/settings/accounts/AccountSyncPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountSyncPreferenceController.java
@@ -25,6 +25,7 @@
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceController;
@@ -53,8 +54,9 @@
final Bundle args = new Bundle();
args.putParcelable(AccountSyncSettings.ACCOUNT_KEY, mAccount);
args.putParcelable(EXTRA_USER, mUserHandle);
- Utils.startWithFragment(mContext, AccountSyncSettings.class.getName(), args, null, 0, -1,
- mAccount.name, MetricsProto.MetricsEvent.ACCOUNT);
+ Utils.startWithFragment(mContext, AccountSyncSettings.class.getName(), args, null, 0,
+ R.string.account_sync_title, null, MetricsProto.MetricsEvent.ACCOUNT);
+
return true;
}
diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java
index 0676f56..5ad5e48 100644
--- a/src/com/android/settings/applications/AppStorageSettings.java
+++ b/src/com/android/settings/applications/AppStorageSettings.java
@@ -99,6 +99,7 @@
private static final String KEY_CLEAR_URI = "clear_uri_button";
private static final String KEY_CACHE_CLEARED = "cache_cleared";
+ private static final String KEY_DATA_CLEARED = "data_cleared";
// Views related to cache info
private Preference mCacheSize;
@@ -115,6 +116,7 @@
private boolean mCanClearData = true;
private boolean mCacheCleared;
+ private boolean mDataCleared;
private AppStorageSizesController mSizeController;
@@ -130,6 +132,8 @@
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCacheCleared = savedInstanceState.getBoolean(KEY_CACHE_CLEARED, false);
+ mDataCleared = savedInstanceState.getBoolean(KEY_DATA_CLEARED, false);
+ mCacheCleared = mCacheCleared || mDataCleared;
}
addPreferencesFromResource(R.xml.app_storage_settings);
@@ -147,6 +151,7 @@
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_CACHE_CLEARED, mCacheCleared);
+ outState.putBoolean(KEY_DATA_CLEARED, mDataCleared);
}
private void setupViews() {
@@ -527,6 +532,9 @@
if (mCacheCleared) {
mSizeController.setCacheCleared(true);
}
+ if (mDataCleared) {
+ mSizeController.setDataCleared(true);
+ }
mSizeController.updateUi(getContext());
@@ -538,7 +546,7 @@
long dataSize = result.getDataBytes();
long cacheSize = result.getCacheBytes();
- if (dataSize <= 0 || !mCanClearData) {
+ if (dataSize <= 0 || !mCanClearData || mDataCleared) {
mClearDataButton.setEnabled(false);
} else {
mClearDataButton.setEnabled(true);
@@ -564,6 +572,8 @@
}
switch (msg.what) {
case MSG_CLEAR_USER_DATA:
+ mDataCleared = true;
+ mCacheCleared = true;
processClearMsg(msg);
break;
case MSG_CLEAR_CACHE:
diff --git a/src/com/android/settings/applications/AppStorageSizesController.java b/src/com/android/settings/applications/AppStorageSizesController.java
index 23a3eb2..45ece6e 100644
--- a/src/com/android/settings/applications/AppStorageSizesController.java
+++ b/src/com/android/settings/applications/AppStorageSizesController.java
@@ -40,6 +40,7 @@
private StorageStatsSource.AppStorageStats mLastResult;
private boolean mLastResultFailed;
private boolean mCachedCleared;
+ private boolean mDataCleared;
private long mLastCodeSize = -1;
private long mLastDataSize = -1;
private long mLastCacheSize = -1;
@@ -69,7 +70,7 @@
mTotalSize.setSummary(errorRes);
} else {
long codeSize = mLastResult.getCodeBytes();
- long dataSize = mLastResult.getDataBytes();
+ long dataSize = mDataCleared ? 0 : mLastResult.getDataBytes();
if (mLastCodeSize != codeSize) {
mLastCodeSize = codeSize;
mAppSize.setSummary(getSizeStr(context, codeSize));
@@ -78,7 +79,7 @@
mLastDataSize = dataSize;
mDataSize.setSummary(getSizeStr(context, dataSize));
}
- long cacheSize = mCachedCleared ? 0 : mLastResult.getCacheBytes();
+ long cacheSize = (mDataCleared || mCachedCleared) ? 0 : mLastResult.getCacheBytes();
if (mLastCacheSize != cacheSize) {
mLastCacheSize = cacheSize;
mCacheSize.setSummary(getSizeStr(context, cacheSize));
@@ -111,6 +112,15 @@
}
/**
+ * Sets if we have cleared data and should zero the data bytes.
+ * When the data is cleared, the directory are recreated. Directories have some size, but are
+ * empty. We zero this out to best match user expectations.
+ */
+ public void setDataCleared(boolean isCleared) {
+ mDataCleared = isCleared;
+ }
+
+ /**
* Returns the last result calculated, if it exists. If it does not, returns null.
*/
public StorageStatsSource.AppStorageStats getLastResult() {
diff --git a/src/com/android/settings/applications/InstalledAppDetails.java b/src/com/android/settings/applications/InstalledAppDetails.java
index 16621f4..c0d2dd8 100755
--- a/src/com/android/settings/applications/InstalledAppDetails.java
+++ b/src/com/android/settings/applications/InstalledAppDetails.java
@@ -454,6 +454,10 @@
@Override
public void onPackageSizeChanged(String packageName) {
+ if (!TextUtils.equals(packageName, mPackageName)) {
+ Log.d(LOG_TAG, "Package change irrelevant, skipping");
+ return;
+ }
refreshUi();
}
diff --git a/src/com/android/settings/applications/defaultapps/AutofillPickerActivity.java b/src/com/android/settings/applications/defaultapps/AutofillPickerActivity.java
new file mode 100644
index 0000000..a173909
--- /dev/null
+++ b/src/com/android/settings/applications/defaultapps/AutofillPickerActivity.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.applications.defaultapps;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+
+/**
+ * Standalone activity used to launch {@link DefaultAppPickerFragment} from a
+ * {@link android.provider.Settings#ACTION_REQUEST_SET_AUTOFILL_SERVICE} intent.
+ */
+public class AutofillPickerActivity extends SettingsActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ final Intent intent = getIntent();
+ final String packageName = intent.getData().getSchemeSpecificPart();
+ intent.putExtra(EXTRA_SHOW_FRAGMENT, DefaultAutofillPicker.class.getName());
+ intent.putExtra(EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.autofill_app);
+ intent.putExtra(DefaultAutofillPicker.EXTRA_PACKAGE_NAME, packageName);
+
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ return super.isValidFragment(fragmentName)
+ || DefaultAutofillPicker.class.getName().equals(fragmentName);
+ }
+}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
index 8eb1fc6..037cddf 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPicker.java
@@ -16,6 +16,7 @@
package com.android.settings.applications.defaultapps;
+import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -38,6 +39,8 @@
static final String SETTING = Settings.Secure.AUTOFILL_SERVICE;
static final Intent AUTOFILL_PROBE = new Intent(AutofillService.SERVICE_INTERFACE);
+ static final String EXTRA_PACKAGE_NAME = "package_name";
+
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.DEFAULT_AUTOFILL_PICKER;
@@ -79,11 +82,24 @@
@Override
protected boolean setDefaultKey(String key) {
Settings.Secure.putString(getContext().getContentResolver(), SETTING, key);
+
+ // Check if activity was launched from Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE
+ // intent, and set proper result if so...
+ final Activity activity = getActivity();
+ if (activity != null) {
+ final String packageName = activity.getIntent().getStringExtra(EXTRA_PACKAGE_NAME);
+ if (packageName != null) {
+ final int result = key != null && key.startsWith(packageName) ? Activity.RESULT_OK
+ : Activity.RESULT_CANCELED;
+ activity.setResult(result);
+ activity.finish();
+ }
+ }
return true;
}
/**
- * Provides Intent to setting activity for the specified auto-fill service.
+ * Provides Intent to setting activity for the specified autofill service.
*/
static final class AutofillSettingIntentProvider implements SettingIntentProvider {
diff --git a/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceController.java b/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceController.java
index c071570..508d6c9 100644
--- a/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceController.java
+++ b/src/com/android/settings/bluetooth/BluetoothMasterSwitchPreferenceController.java
@@ -36,7 +36,7 @@
implements OnSummaryChangeListener,
LifecycleObserver, OnResume, OnPause, OnStart, OnStop {
- private static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth";
+ public static final String KEY_TOGGLE_BLUETOOTH = "toggle_bluetooth";
private LocalBluetoothManager mBluetoothManager;
private MasterSwitchPreference mBtPreference;
diff --git a/src/com/android/settings/bluetooth/BluetoothSummaryUpdater.java b/src/com/android/settings/bluetooth/BluetoothSummaryUpdater.java
index 282f613..5a2dcb2 100644
--- a/src/com/android/settings/bluetooth/BluetoothSummaryUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothSummaryUpdater.java
@@ -17,14 +17,22 @@
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+
import com.android.settings.R;
import com.android.settings.widget.SummaryUpdater;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
+import java.util.Set;
/**
* Helper class that listeners to bluetooth callback and notify client when there is update in
@@ -98,7 +106,7 @@
}
switch (mConnectionState) {
case BluetoothAdapter.STATE_CONNECTED:
- return mContext.getString(R.string.bluetooth_connected_summary);
+ return getConnectedDeviceSummary();
case BluetoothAdapter.STATE_CONNECTING:
return mContext.getString(R.string.bluetooth_connecting);
case BluetoothAdapter.STATE_DISCONNECTING:
@@ -145,4 +153,27 @@
: null;
}
+ @VisibleForTesting
+ String getConnectedDeviceSummary() {
+ String deviceName = null;
+ int count = 0;
+ final Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
+ if (devices == null || devices.isEmpty()) {
+ return null;
+ }
+
+ for (BluetoothDevice device : devices) {
+ if (device.isConnected()) {
+ deviceName = device.getName();
+ count++;
+ if (count > 1) {
+ break;
+ }
+ }
+ }
+
+ return count > 1 ? mContext.getString(R.string.bluetooth_connected_multiple_devices_summary)
+ : mContext.getString(R.string.bluetooth_connected_summary, deviceName);
+ }
+
}
diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
index b12e849..aeb7efb 100644
--- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
+++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java
@@ -16,6 +16,7 @@
package com.android.settings.connecteddevice;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto;
@@ -85,5 +86,20 @@
sir.xmlResId = R.xml.connected_devices;
return Arrays.asList(sir);
}
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ PackageManager pm = context.getPackageManager();
+ final List<String> keys = new ArrayList<String>();
+
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
+ keys.add(NfcPreferenceController.KEY_TOGGLE_NFC);
+ keys.add(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
+ }
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) {
+ keys.add(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
+ }
+ return keys;
+ }
};
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
index 1be2c68..bdd5c60 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
@@ -17,19 +17,13 @@
package com.android.settings.dashboard.suggestions;
import android.app.AutomaticZenRule;
-import android.app.IWallpaperManager;
-import android.app.IWallpaperManager.Stub;
-import android.app.IWallpaperManagerCallback;
import android.app.KeyguardManager;
import android.app.NotificationManager;
import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
+import android.support.annotation.VisibleForTesting;
import com.android.ims.ImsManager;
import com.android.settings.Settings.FingerprintEnrollSuggestionActivity;
@@ -49,10 +43,14 @@
*/
public class SuggestionsChecks {
+ private static final String TAG = "SuggestionsChecks";
private final Context mContext;
+ private final WallpaperManagerWrapper mWallpaperManager;
+
public SuggestionsChecks(Context context) {
mContext = context.getApplicationContext();
+ mWallpaperManager = new WallpaperManagerWrapper(mContext);
}
public boolean isSuggestionComplete(Tile suggestion) {
@@ -76,7 +74,7 @@
}
SuggestionFeatureProvider provider =
- FeatureFactory.getFactory(mContext).getSuggestionFeatureProvider(mContext);
+ FeatureFactory.getFactory(mContext).getSuggestionFeatureProvider(mContext);
if (provider != null && provider.isPresent(className)) {
return provider.isSuggestionCompleted(mContext);
}
@@ -114,16 +112,9 @@
return false;
}
- private boolean hasWallpaperSet() {
- IBinder b = ServiceManager.getService(Context.WALLPAPER_SERVICE);
- IWallpaperManager service = Stub.asInterface(b);
- try {
- return !service.isSetWallpaperAllowed(mContext.getOpPackageName()) ||
- service.getWallpaper(mCallback, WallpaperManager.FLAG_SYSTEM,
- new Bundle(), mContext.getUserId()) != null;
- } catch (RemoteException e) {
- }
- return false;
+ @VisibleForTesting
+ boolean hasWallpaperSet() {
+ return mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM) > 0;
}
private boolean isFingerprintEnabled() {
@@ -133,11 +124,4 @@
mContext.getUserId());
return (dpmFlags & DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT) == 0;
}
-
- private final IWallpaperManagerCallback mCallback = new IWallpaperManagerCallback.Stub() {
- @Override
- public void onWallpaperChanged() throws RemoteException {
- // Don't care.
- }
- };
}
diff --git a/src/com/android/settings/dashboard/suggestions/WallpaperManagerWrapper.java b/src/com/android/settings/dashboard/suggestions/WallpaperManagerWrapper.java
new file mode 100644
index 0000000..9efe4fe
--- /dev/null
+++ b/src/com/android/settings/dashboard/suggestions/WallpaperManagerWrapper.java
@@ -0,0 +1,33 @@
+/*
+ * 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.dashboard.suggestions;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+
+public class WallpaperManagerWrapper {
+
+ private final WallpaperManager mWallpaperManager;
+
+ public WallpaperManagerWrapper(Context context) {
+ mWallpaperManager = (WallpaperManager) context.getSystemService(Context.WALLPAPER_SERVICE);
+ }
+
+ public int getWallpaperId(int which) {
+ return mWallpaperManager.getWallpaperId(which);
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
index ca0348c..c6337ce 100644
--- a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
+++ b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java
@@ -98,7 +98,9 @@
mVolume = mStorageManager.findVolumeByUuid(fsUuid);
} else {
final String volId = getArguments().getString(VolumeInfo.EXTRA_VOLUME_ID);
- mVolume = mStorageManager.findVolumeById(volId);
+ if (volId != null) {
+ mVolume = mStorageManager.findVolumeById(volId);
+ }
}
if (!isVolumeValid()) {
@@ -129,6 +131,12 @@
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
+
+ // If the volume isn't valid, we are not scaffolded to set up a view.
+ if (!isVolumeValid()) {
+ return;
+ }
+
final Resources resources = getResources();
final int padding = resources.getDimensionPixelSize(
R.dimen.unmount_button_padding);
diff --git a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
index 31ca148..377ec1e 100644
--- a/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceController.java
@@ -214,6 +214,15 @@
mAppPreference = (StorageItemPreference) screen.findPreference(OTHER_APPS_KEY);
mSystemPreference = (StorageItemPreference) screen.findPreference(SYSTEM_KEY);
mFilePreference = (StorageItemPreference) screen.findPreference(FILES_KEY);
+
+ final VolumeInfo sharedVolume = mSvp.findEmulatedForPrivate(mVolume);
+ // If we don't have a shared volume for our internal storage (or the shared volume isn't
+ // mounted as readable for whatever reason), we should hide the File preference.
+ final boolean hideFilePreference =
+ (sharedVolume == null) || !sharedVolume.isMountedReadable();
+ if (hideFilePreference) {
+ screen.removePreference(mFilePreference);
+ }
}
public void onLoadFinished(StorageAsyncLoader.AppsStorageResult data) {
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index a73902a..0cbfd54 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -28,6 +28,7 @@
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
+import android.text.TextUtils;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -40,6 +41,7 @@
import com.android.settings.applications.AppHeaderController;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.enterprise.DevicePolicyManagerWrapper;
import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
import com.android.settings.overlay.FeatureFactory;
@@ -55,7 +57,7 @@
* 2. Battery related controls for app(i.e uninstall, force stop)
*
*/
-public class AdvancedPowerUsageDetail extends PowerUsageBase implements
+public class AdvancedPowerUsageDetail extends DashboardFragment implements
ButtonActionDialogFragment.AppButtonsDialogListener {
public static final String TAG = "AdvancedPowerUsageDetail";
@@ -82,6 +84,8 @@
ApplicationsState mState;
@VisibleForTesting
ApplicationsState.AppEntry mAppEntry;
+ @VisibleForTesting
+ BatteryUtils mBatteryUtils;
private Preference mForegroundPreference;
private Preference mBackgroundPreference;
@@ -137,6 +141,7 @@
(DevicePolicyManager) activity.getSystemService(Context.DEVICE_POLICY_SERVICE));
mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
mPackageManager = activity.getPackageManager();
+ mBatteryUtils = BatteryUtils.getInstance(getContext());
}
@Override
diff --git a/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java b/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java
new file mode 100644
index 0000000..b99519b
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/BatteryStatsHelperLoader.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
+
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.utils.AsyncLoader;
+
+/**
+ * Loader to get new {@link BatteryStatsHelper} in the background
+ */
+public class BatteryStatsHelperLoader extends AsyncLoader<BatteryStatsHelper> {
+ @VisibleForTesting
+ UserManager mUserManager;
+ private Bundle mBundle;
+
+ public BatteryStatsHelperLoader(Context context, Bundle bundle) {
+ super(context);
+ mBundle = bundle;
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ }
+
+ @Override
+ public BatteryStatsHelper loadInBackground() {
+ final BatteryStatsHelper statsHelper = new BatteryStatsHelper(getContext(), true);
+
+ initBatteryStatsHelper(statsHelper);
+ return statsHelper;
+ }
+
+ @Override
+ protected void onDiscardResult(BatteryStatsHelper result) {
+
+ }
+
+ @VisibleForTesting
+ void initBatteryStatsHelper(BatteryStatsHelper statsHelper) {
+ statsHelper.create(mBundle);
+ statsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, mUserManager.getUserProfiles());
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index 48e2421..dad7b59 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -15,14 +15,13 @@
*/
package com.android.settings.fuelgauge;
-import android.annotation.IntDef;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.BatteryStats;
import android.os.SystemClock;
+import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
-import android.text.format.DateUtils;
import android.util.Log;
import com.android.internal.os.BatterySipper;
@@ -64,7 +63,8 @@
return sInstance;
}
- private BatteryUtils(Context context) {
+ @VisibleForTesting
+ BatteryUtils(Context context) {
mPackageManager = context.getPackageManager();
mPowerUsageFeatureProvider = FeatureFactory.getFactory(
context).getPowerUsageFeatureProvider(context);
@@ -102,7 +102,6 @@
final long rawRealTimeUs = convertMsToUs(SystemClock.elapsedRealtime());
final int foregroundTypes[] = {BatteryStats.Uid.PROCESS_STATE_TOP,
BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE,
- BatteryStats.Uid.PROCESS_STATE_TOP_SLEEPING,
BatteryStats.Uid.PROCESS_STATE_FOREGROUND};
Log.v(TAG, "package: " + mPackageManager.getNameForUid(uid.getUid()));
@@ -129,9 +128,8 @@
final BatterySipper sipper = sippers.get(i);
if (shouldHideSipper(sipper)) {
sippers.remove(i);
- if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED
- && sipper.drainType != BatterySipper.DrainType.UNACCOUNTED) {
- // Don't add it if it is overcounted or unaccounted
+ if (sipper.drainType != BatterySipper.DrainType.OVERCOUNTED) {
+ // Don't add it if it is overcounted
totalPowerMah += sipper.totalPowerMah;
}
}
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index bdadf4c..b124c81 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -79,11 +79,15 @@
return mProgress.toString();
}
- public void setSubtitle(String subtitle) {
+ public void setSubtitle(CharSequence subtitle) {
mProgress = subtitle;
notifyChanged();
}
+ public CharSequence getSubtitle() {
+ return mProgress;
+ }
+
BatteryEntry getInfo() {
return mInfo;
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index b718f8f..4ebff34 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -29,6 +29,7 @@
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
+import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.os.BatterySipper;
@@ -67,13 +68,14 @@
UsageType.APP,
UsageType.UNACCOUNTED,
UsageType.OVERCOUNTED};
+
+ private BatteryUtils mBatteryUtils;
private BatteryHistoryPreference mHistPref;
private PreferenceGroup mUsageListGroup;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
private PackageManager mPackageManager;
private UserManager mUserManager;
private Map<Integer, PowerUsageData> mBatteryDataMap;
- private BatteryUtils mBatteryUtils;
Handler mHandler = new Handler() {
@@ -123,7 +125,6 @@
@Override
public void onResume() {
super.onResume();
- refreshStats();
}
@Override
@@ -162,8 +163,11 @@
}
@Override
- protected void refreshStats() {
- super.refreshStats();
+ protected void refreshUi() {
+ final Context context = getContext();
+ if (context == null) {
+ return;
+ }
updatePreference(mHistPref);
@@ -253,8 +257,10 @@
final List<PowerUsageData> batteryDataList = new ArrayList<>(batteryDataMap.values());
final int dischargeAmount = statusHelper.getStats().getDischargeAmount(STATUS_TYPE);
final double totalPower = statusHelper.getTotalPower();
+ final double hiddenPower = calculateHiddenPower(batteryDataList);
for (final PowerUsageData usageData : batteryDataList) {
- usageData.percentage = (usageData.totalPowerMah / totalPower) * dischargeAmount;
+ usageData.percentage = mBatteryUtils.calculateBatteryPercent(usageData.totalPowerMah,
+ totalPower, hiddenPower, dischargeAmount);
updateUsageDataSummary(usageData, totalPower, dischargeAmount);
}
@@ -265,13 +271,26 @@
}
@VisibleForTesting
+ double calculateHiddenPower(List<PowerUsageData> batteryDataList) {
+ for (final PowerUsageData usageData : batteryDataList) {
+ if (usageData.usageType == UsageType.UNACCOUNTED) {
+ return usageData.totalPowerMah;
+ }
+ }
+
+ return 0;
+ }
+
+ @VisibleForTesting
void updateUsageDataSummary(PowerUsageData usageData, double totalPower, int dischargeAmount) {
if (shouldHideSummary(usageData)) {
return;
}
if (usageData.usageList.size() <= 1) {
- usageData.summary = getString(R.string.battery_used_for,
- Utils.formatElapsedTime(getContext(), usageData.totalUsageTimeMs, false));
+ CharSequence timeSequence = Utils.formatElapsedTime(getContext(),
+ usageData.totalUsageTimeMs, false);
+ usageData.summary = TextUtils.expandTemplate(getText(R.string.battery_used_for),
+ timeSequence);
} else {
BatterySipper sipper = findBatterySipperWithMaxBatteryUsage(usageData.usageList);
BatteryEntry batteryEntry = new BatteryEntry(getContext(), mHandler, mUserManager,
@@ -315,6 +334,10 @@
void setUserManager(UserManager userManager) {
mUserManager = userManager;
}
+ @VisibleForTesting
+ void setBatteryUtils(BatteryUtils batteryUtils) {
+ mBatteryUtils = batteryUtils;
+ }
/**
* Class that contains data used in {@link PowerGaugePreference}.
@@ -346,7 +369,7 @@
@StringRes
public int titleResId;
- public String summary;
+ public CharSequence summary;
public double percentage;
public double totalPowerMah;
public long totalUsageTimeMs;
diff --git a/src/com/android/settings/fuelgauge/PowerUsageBase.java b/src/com/android/settings/fuelgauge/PowerUsageBase.java
index 1d9a228..aee55d6 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageBase.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageBase.java
@@ -16,28 +16,23 @@
package com.android.settings.fuelgauge;
import android.app.Activity;
-import android.content.BroadcastReceiver;
+import android.app.LoaderManager;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryStats;
+import android.content.Loader;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
import android.os.UserManager;
import android.support.annotation.VisibleForTesting;
import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import com.android.internal.os.BatteryStatsHelper;
-import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.utils.AsyncLoader;
/**
* Common base class for things that need to show the battery usage graph.
*/
-public abstract class PowerUsageBase extends DashboardFragment {
+public abstract class PowerUsageBase extends DashboardFragment
+ implements LoaderManager.LoaderCallbacks<BatteryStatsHelper> {
// +1 to allow ordering for PowerUsageSummary.
@VisibleForTesting
@@ -62,27 +57,23 @@
mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(getContext());
mBatteryBroadcastReceiver.setBatteryChangedListener(() -> {
- if (!mHandler.hasMessages(MSG_REFRESH_STATS)) {
- mHandler.sendEmptyMessageDelayed(MSG_REFRESH_STATS, 500);
- }
+ getLoaderManager().restartLoader(0, null, this);
});
+
+ getLoaderManager().initLoader(0, icicle, this);
}
@Override
public void onStart() {
super.onStart();
- mStatsHelper.clearStats();
}
@Override
public void onResume() {
super.onResume();
+
BatteryStatsHelper.dropFile(getActivity(), BatteryHistoryDetail.BATTERY_HISTORY_FILE);
mBatteryBroadcastReceiver.register();
- if (mHandler.hasMessages(MSG_REFRESH_STATS)) {
- mHandler.removeMessages(MSG_REFRESH_STATS);
- mStatsHelper.clearStats();
- }
}
@Override
@@ -94,7 +85,6 @@
@Override
public void onStop() {
super.onStop();
- mHandler.removeMessages(MSG_REFRESH_STATS);
}
@Override
@@ -105,26 +95,27 @@
}
}
- protected void refreshStats() {
- mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, mUm.getUserProfiles());
- }
+ protected abstract void refreshUi();
protected void updatePreference(BatteryHistoryPreference historyPref) {
historyPref.setStats(mStatsHelper);
}
- static final int MSG_REFRESH_STATS = 100;
+ @Override
+ public Loader<BatteryStatsHelper> onCreateLoader(int id,
+ Bundle args) {
+ return new BatteryStatsHelperLoader(getContext(), args);
+ }
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REFRESH_STATS:
- mStatsHelper.clearStats();
- refreshStats();
- break;
- }
- }
- };
+ @Override
+ public void onLoadFinished(Loader<BatteryStatsHelper> loader,
+ BatteryStatsHelper statsHelper) {
+ mStatsHelper = statsHelper;
+ refreshUi();
+ }
+ @Override
+ public void onLoaderReset(Loader<BatteryStatsHelper> loader) {
+
+ }
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 078a9b3..bcf830b 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -18,6 +18,8 @@
import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.BatteryStats;
import android.os.Build;
@@ -142,7 +144,6 @@
@Override
public void onResume() {
super.onResume();
- refreshStats();
}
@Override
@@ -236,7 +237,7 @@
} else {
mStatsType = BatteryStats.STATS_SINCE_CHARGED;
}
- refreshStats();
+ refreshUi();
return true;
case MENU_HIGH_POWER_APPS:
Bundle args = new Bundle();
@@ -259,7 +260,7 @@
item.setTitle(mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE, mShowAllApps);
- refreshStats();
+ refreshUi();
return true;
default:
return super.onOptionsItemSelected(item);
@@ -396,15 +397,11 @@
return results;
}
- protected void refreshStats() {
- super.refreshStats();
-
- BatteryInfo.getBatteryInfo(getContext(), new BatteryInfo.Callback() {
- @Override
- public void onBatteryInfoLoaded(BatteryInfo info) {
- updateHeaderPreference(info);
- }
- });
+ protected void refreshUi() {
+ final Context context = getContext();
+ if (context == null) {
+ return;
+ }
cacheRemoveAllPrefs(mAppListGroup);
mAppListGroup.setOrderingAsAdded(false);
@@ -413,20 +410,27 @@
final PowerProfile powerProfile = mStatsHelper.getPowerProfile();
final BatteryStats stats = mStatsHelper.getStats();
final double averagePower = powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
- final Context context = getContext();
+
+ final long elapsedRealtimeUs = SystemClock.elapsedRealtime() * 1000;
+ Intent batteryBroadcast = context.registerReceiver(null,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ BatteryInfo batteryInfo = BatteryInfo.getBatteryInfo(context, batteryBroadcast,
+ mStatsHelper.getStats(), elapsedRealtimeUs, false);
+ updateHeaderPreference(batteryInfo);
final TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.colorControlNormal, value, true);
final int colorControl = context.getColor(value.resourceId);
- final String usedTime = context.getString(R.string.battery_used_for);
final int dischargeAmount = USE_FAKE_DATA ? 5000
: stats != null ? stats.getDischargeAmount(mStatsType) : 0;
final long runningTime = calculateRunningTimeBasedOnStatsType();
updateScreenPreference();
updateLastFullChargePreference(runningTime);
- mAppListGroup.setTitle(getString(R.string.power_usage_list_summary,
- Utils.formatElapsedTime(context, runningTime, false)));
+
+ final CharSequence timeSequence = Utils.formatElapsedTime(context, runningTime, false);
+ mAppListGroup.setTitle(
+ TextUtils.expandTemplate(getText(R.string.power_usage_list_summary), timeSequence));
if (averagePower >= MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP || USE_FAKE_DATA) {
final List<BatterySipper> usageList = getCoalescedUsageList(
@@ -497,7 +501,7 @@
sipper.usageTimeMs = mBatteryUtils.getProcessTimeMs(
BatteryUtils.StatusType.FOREGROUND, sipper.uidObj, mStatsType);
}
- setUsageSummary(pref, usedTime, sipper.usageTimeMs);
+ setUsageSummary(pref, sipper.usageTimeMs);
if ((sipper.drainType != DrainType.APP
|| sipper.uidObj.getUid() == Process.ROOT_UID)
&& sipper.drainType != DrainType.USER) {
@@ -534,16 +538,17 @@
void updateScreenPreference() {
final BatterySipper sipper = findBatterySipperByType(
mStatsHelper.getUsageList(), DrainType.SCREEN);
- final Context context = getContext();
final long usageTimeMs = sipper != null ? sipper.usageTimeMs : 0;
- mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(context, usageTimeMs, false));
+ mScreenUsagePref.setSubtitle(Utils.formatElapsedTime(getContext(), usageTimeMs, false));
}
@VisibleForTesting
void updateLastFullChargePreference(long timeMs) {
- mLastFullChargePref.setSubtitle(getString(R.string.power_last_full_charge_summary,
- Utils.formatElapsedTime(getContext(), timeMs, false)));
+ final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), timeMs, false);
+ mLastFullChargePref.setSubtitle(
+ TextUtils.expandTemplate(getText(R.string.power_last_full_charge_summary),
+ timeSequence));
}
@VisibleForTesting
@@ -583,11 +588,13 @@
}
@VisibleForTesting
- void setUsageSummary(Preference preference, String usedTimePrefix, long usageTimeMs) {
+ void setUsageSummary(Preference preference, long usageTimeMs) {
// Only show summary when usage time is longer than one minute
if (usageTimeMs >= DateUtils.MINUTE_IN_MILLIS) {
- preference.setSummary(String.format(usedTimePrefix,
- Utils.formatElapsedTime(getContext(), usageTimeMs, false)));
+ final CharSequence timeSequence = Utils.formatElapsedTime(getContext(), usageTimeMs,
+ false);
+ preference.setSummary(
+ TextUtils.expandTemplate(getText(R.string.battery_used_for), timeSequence));
}
}
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index 11e3e09..7164b5b 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -39,8 +39,8 @@
public class NfcPreferenceController extends PreferenceController
implements LifecycleObserver, OnResume, OnPause {
- private static final String KEY_TOGGLE_NFC = "toggle_nfc";
- private static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
+ public static final String KEY_TOGGLE_NFC = "toggle_nfc";
+ public static final String KEY_ANDROID_BEAM_SETTINGS = "android_beam_settings";
private NfcEnabler mNfcEnabler;
private NfcAdapter mNfcAdapter;
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index bcf9c3f..db5cf2f 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -19,6 +19,7 @@
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import android.app.Activity;
import android.app.NotificationChannel;
@@ -251,12 +252,14 @@
private void setupImportanceToggle() {
mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
- mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT);
+ mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
+ || mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
mImportanceToggle.setOnPreferenceChangeListener(
new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- final int importance = ((Boolean) newValue ? IMPORTANCE_DEFAULT : IMPORTANCE_LOW);
+ final int importance =
+ ((Boolean) newValue ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_LOW);
mChannel.setImportance(importance);
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
mBackend.updateChannel(mPkg, mUid, mChannel);
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index aee9dc2..b591d85 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -17,21 +17,24 @@
package com.android.settings.notification;
import android.content.Context;
+import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.PreferenceController;
+import com.android.settings.core.lifecycle.Lifecycle;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.gestures.SwipeToNotificationPreferenceController;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
public class ConfigureNotificationSettings extends DashboardFragment {
private static final String TAG = "ConfigNotiSettings";
- private LockScreenNotificationPreferenceController mLockScreenNotificationController;
-
@Override
public int getMetricsCategory() {
return MetricsEvent.CONFIGURE_NOTIFICATION;
@@ -49,15 +52,42 @@
@Override
protected List<PreferenceController> getPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getLifecycle());
+ }
+
+ private static List<PreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
final List<PreferenceController> controllers = new ArrayList<>();
final PulseNotificationPreferenceController pulseController =
new PulseNotificationPreferenceController(context);
- mLockScreenNotificationController = new LockScreenNotificationPreferenceController(context);
- getLifecycle().addObserver(pulseController);
- getLifecycle().addObserver(mLockScreenNotificationController);
- controllers.add(new SwipeToNotificationPreferenceController(context, getLifecycle()));
+ final LockScreenNotificationPreferenceController lockScreenNotificationController =
+ new LockScreenNotificationPreferenceController(context);
+ if (lifecycle != null) {
+ lifecycle.addObserver(pulseController);
+ lifecycle.addObserver(lockScreenNotificationController);
+ }
+ controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle));
controllers.add(pulseController);
- controllers.add(mLockScreenNotificationController);
+ controllers.add(lockScreenNotificationController);
return controllers;
}
+
+ /**
+ * For Search.
+ */
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.configure_notification_settings;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ public List<PreferenceController> getPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+ };
}
diff --git a/src/com/android/settings/search/BaseSearchIndexProvider.java b/src/com/android/settings/search/BaseSearchIndexProvider.java
index 54f66ea..bda9319 100644
--- a/src/com/android/settings/search/BaseSearchIndexProvider.java
+++ b/src/com/android/settings/search/BaseSearchIndexProvider.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.provider.SearchIndexableResource;
+import android.support.annotation.CallSuper;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
@@ -57,6 +58,7 @@
}
@Override
+ @CallSuper
public List<String> getNonIndexableKeys(Context context) {
if (!isPageSearchEnabled(context)) {
// Entire page should be suppressed, mark all keys from this page as non-indexable.
diff --git a/src/com/android/settings/search2/DatabaseIndexingManager.java b/src/com/android/settings/search2/DatabaseIndexingManager.java
index 533884d..ccc5283 100644
--- a/src/com/android/settings/search2/DatabaseIndexingManager.java
+++ b/src/com/android/settings/search2/DatabaseIndexingManager.java
@@ -515,7 +515,7 @@
if (count > 0) {
while (cursor.moveToNext()) {
final int providerRank = cursor.getInt(COLUMN_INDEX_XML_RES_RANK);
-
+ // TODO remove provider rank
final int xmlResId = cursor.getInt(COLUMN_INDEX_XML_RES_RESID);
final String className = cursor.getString(COLUMN_INDEX_XML_RES_CLASS_NAME);
@@ -560,7 +560,7 @@
if (count > 0) {
while (cursor.moveToNext()) {
final int providerRank = cursor.getInt(COLUMN_INDEX_RAW_RANK);
-
+ // TODO Remove rank
final String title = cursor.getString(COLUMN_INDEX_RAW_TITLE);
final String summaryOn = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_ON);
final String summaryOff = cursor.getString(COLUMN_INDEX_RAW_SUMMARY_OFF);
@@ -749,7 +749,6 @@
.setEntries(null)
.setClassName(fragmentName)
.setScreenTitle(screenTitle)
- .setIconResId(iconResId)
.setRank(rank)
.setIntentAction(intentAction)
.setIntentTargetPackage(intentTargetPackage)
diff --git a/src/com/android/settings/search2/SearchFragment.java b/src/com/android/settings/search2/SearchFragment.java
index 8e1e1b4..c5db08d 100644
--- a/src/com/android/settings/search2/SearchFragment.java
+++ b/src/com/android/settings/search2/SearchFragment.java
@@ -168,6 +168,17 @@
}
@Override
+ public void onResume() {
+ super.onResume();
+ if (TextUtils.isEmpty(mQuery)) {
+ return;
+ }
+ final String query = mQuery;
+ mQuery = "";
+ onQueryTextChange(query);
+ }
+
+ @Override
public void onStop() {
super.onStop();
final Activity activity = getActivity();
@@ -206,7 +217,6 @@
mResultClickCount = 0;
mNeverEnteredQuery = false;
mQuery = query;
- mSearchAdapter.clearResults();
if (isEmptyQuery) {
final LoaderManager loaderManager = getLoaderManager();
@@ -252,7 +262,13 @@
return;
}
final int resultCount = mSearchAdapter.displaySearchResults();
- mNoResultsView.setVisibility(resultCount == 0 ? View.VISIBLE : View.GONE);
+
+ if (resultCount == 0) {
+ mNoResultsView.setVisibility(View.VISIBLE);
+ } else {
+ mNoResultsView.setVisibility(View.GONE);
+ mResultsRecyclerView.scrollToPosition(0);
+ }
mSearchFeatureProvider.showFeedbackButton(this, getView());
}
diff --git a/src/com/android/settings/search2/SearchResult.java b/src/com/android/settings/search2/SearchResult.java
index 6b27d89..ecc41b6 100644
--- a/src/com/android/settings/search2/SearchResult.java
+++ b/src/com/android/settings/search2/SearchResult.java
@@ -93,7 +93,7 @@
icon = builder.mIcon;
payload = builder.mResultPayload;
viewType = payload.getType();
- stableId = Objects.hash(title, summary, breadcrumbs, rank, icon, payload, viewType);
+ stableId = Objects.hash(title, summary, breadcrumbs, rank, viewType);
}
@Override
@@ -104,6 +104,22 @@
return this.rank - searchResult.rank;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SearchResult)) {
+ return false;
+ }
+ return this.stableId == ((SearchResult) obj).stableId;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) stableId;
+ }
+
public static class Builder {
protected CharSequence mTitle;
protected CharSequence mSummary;
@@ -127,19 +143,19 @@
return this;
}
- public Builder addRank(int rank) {
+ public Builder addRank(int rank) {
if (rank >= 0 && rank <= 9) {
mRank = rank;
}
return this;
}
- public Builder addIcon(Drawable icon) {
+ public Builder addIcon(Drawable icon) {
mIcon = icon;
return this;
}
- public Builder addPayload(ResultPayload payload) {
+ public Builder addPayload(ResultPayload payload) {
mResultPayload = payload;
return this;
}
diff --git a/src/com/android/settings/search2/SearchResultDiffCallback.java b/src/com/android/settings/search2/SearchResultDiffCallback.java
new file mode 100644
index 0000000..9bd1bde
--- /dev/null
+++ b/src/com/android/settings/search2/SearchResultDiffCallback.java
@@ -0,0 +1,56 @@
+/*
+ * 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.search2;
+
+import android.support.v7.util.DiffUtil;
+
+import java.util.List;
+
+/**
+ * Callback for DiffUtil to elegantly update search data when the query changes.
+ */
+public class SearchResultDiffCallback extends DiffUtil.Callback {
+
+ private List<SearchResult> mOldList;
+ private List<SearchResult> mNewList;
+
+ public SearchResultDiffCallback(List<SearchResult> oldList, List<SearchResult> newList) {
+ mOldList = oldList;
+ mNewList = newList;
+ }
+
+ @Override
+ public int getOldListSize() {
+ return mOldList.size();
+ }
+
+ @Override
+ public int getNewListSize() {
+ return mNewList.size();
+ }
+
+ @Override
+ public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
+ return mOldList.get(oldItemPosition).equals(mNewList.get(newItemPosition));
+ }
+
+ @Override
+ public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
+ return mOldList.get(oldItemPosition).equals(mNewList.get(newItemPosition));
+ }
+}
diff --git a/src/com/android/settings/search2/SearchResultsAdapter.java b/src/com/android/settings/search2/SearchResultsAdapter.java
index 6ff68b1..60f2f7c 100644
--- a/src/com/android/settings/search2/SearchResultsAdapter.java
+++ b/src/com/android/settings/search2/SearchResultsAdapter.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.support.annotation.MainThread;
import android.support.annotation.VisibleForTesting;
+import android.support.v7.util.DiffUtil;
import android.support.v7.widget.RecyclerView;
import android.util.ArrayMap;
import android.view.LayoutInflater;
@@ -37,8 +38,9 @@
public class SearchResultsAdapter extends RecyclerView.Adapter<SearchViewHolder> {
- private final List<SearchResult> mSearchResults;
private final SearchFragment mFragment;
+
+ private List<SearchResult> mSearchResults;
private Map<String, List<? extends SearchResult>> mResultsMap;
public SearchResultsAdapter(SearchFragment fragment) {
@@ -128,7 +130,7 @@
.get(InstalledAppResultLoader.class.getName());
final int dbSize = (databaseResults != null) ? databaseResults.size() : 0;
final int appSize = (installedAppResults != null) ? installedAppResults.size() : 0;
- final List<SearchResult> results = new ArrayList<>(dbSize + appSize);
+ final List<SearchResult> newResults = new ArrayList<>(dbSize + appSize);
int dbIndex = 0;
int appIndex = 0;
@@ -136,23 +138,25 @@
while (rank <= BOTTOM_RANK) {
while ((dbIndex < dbSize) && (databaseResults.get(dbIndex).rank == rank)) {
- results.add(databaseResults.get(dbIndex++));
+ newResults.add(databaseResults.get(dbIndex++));
}
while ((appIndex < appSize) && (installedAppResults.get(appIndex).rank == rank)) {
- results.add(installedAppResults.get(appIndex++));
+ newResults.add(installedAppResults.get(appIndex++));
}
rank++;
}
while (dbIndex < dbSize) {
- results.add(databaseResults.get(dbIndex++));
+ newResults.add(databaseResults.get(dbIndex++));
}
while (appIndex < appSize) {
- results.add(installedAppResults.get(appIndex++));
+ newResults.add(installedAppResults.get(appIndex++));
}
- mSearchResults.addAll(results);
- notifyDataSetChanged();
+ final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(
+ new SearchResultDiffCallback(mSearchResults, newResults), false /* detectMoves */);
+ mSearchResults = newResults;
+ diffResult.dispatchUpdatesTo(this);
return mSearchResults.size();
}
diff --git a/src/com/android/settings/search2/SearchViewHolder.java b/src/com/android/settings/search2/SearchViewHolder.java
index 123a602..fef9367 100644
--- a/src/com/android/settings/search2/SearchViewHolder.java
+++ b/src/com/android/settings/search2/SearchViewHolder.java
@@ -66,9 +66,11 @@
iconView.setImageDrawable(appResult.info.loadIcon(pm));
} else if (result.icon != null) {
iconView.setImageDrawable(result.icon);
+ // TODO set color of icon
} else {
iconView.setBackgroundResource(R.drawable.empty_icon);
}
+
bindBreadcrumbView(result);
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 240b8eb..f5462b0 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -1,7 +1,5 @@
-com.android.settings.notification.ConfigureNotificationSettings
com.android.settings.language.LanguageAndRegionSettings
com.android.settings.notification.ZenModePrioritySettings
-com.android.settings.inputmethod.InputAndGestureSettings
com.android.settings.accounts.AccountDetailDashboardFragment
com.android.settings.fuelgauge.PowerUsageDetail
com.android.settings.fuelgauge.AdvancedPowerUsageDetail
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index 8b7605c..8dfd32a 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -19,7 +19,10 @@
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
import android.text.format.DateUtils;
+import android.text.style.TtsSpan;
import org.junit.Before;
import org.junit.Test;
@@ -35,10 +38,14 @@
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class UtilsTest {
+ private static final String TIME_DESCRIPTION = "1 day 20 hours 30 minutes";
private Context mContext;
- @Mock private WifiManager wifiManager;
- @Mock private Network network;
- @Mock private ConnectivityManager connectivityManager;
+ @Mock
+ private WifiManager wifiManager;
+ @Mock
+ private Network network;
+ @Mock
+ private ConnectivityManager connectivityManager;
@Before
public void setUp() {
@@ -47,7 +54,7 @@
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(WifiManager.class)).thenReturn(wifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
- .thenReturn(connectivityManager);
+ .thenReturn(connectivityManager);
}
@Test
@@ -89,7 +96,8 @@
final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS;
final String expectedTime = "5m 0s";
- assertThat(Utils.formatElapsedTime(mContext, testMillis, true)).isEqualTo(expectedTime);
+ assertThat(Utils.formatElapsedTime(mContext, testMillis, true).toString()).isEqualTo(
+ expectedTime);
}
@Test
@@ -97,7 +105,8 @@
final double testMillis = 5 * DateUtils.MINUTE_IN_MILLIS;
final String expectedTime = "5m";
- assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime);
+ assertThat(Utils.formatElapsedTime(mContext, testMillis, false).toString()).isEqualTo(
+ expectedTime);
}
@Test
@@ -106,7 +115,23 @@
+ 4 * DateUtils.HOUR_IN_MILLIS + 15 * DateUtils.MINUTE_IN_MILLIS;
final String expectedTime = "2d 4h 15m";
- assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime);
+ assertThat(Utils.formatElapsedTime(mContext, testMillis, false).toString()).isEqualTo(
+ expectedTime);
+ }
+
+ @Test
+ public void testFormatElapsedTime_onlyContainsMinute_hasTtsSpan() {
+ final double testMillis = 15 * DateUtils.MINUTE_IN_MILLIS;
+
+ final CharSequence charSequence = Utils.formatElapsedTime(mContext, testMillis, false);
+ assertThat(charSequence).isInstanceOf(SpannableStringBuilder.class);
+
+ final SpannableStringBuilder expectedString = (SpannableStringBuilder) charSequence;
+ final TtsSpan[] ttsSpans = expectedString.getSpans(0, expectedString.length(),
+ TtsSpan.class);
+
+ assertThat(ttsSpans).asList().hasSize(1);
+ assertThat(ttsSpans[0].getType()).isEqualTo(TtsSpan.TYPE_MEASURE);
}
@Test
@@ -119,13 +144,13 @@
}
@Test
- public void getInstallationStatus_notInstalled_shouldReturnUninstalled() {
+ public void testGetInstallationStatus_notInstalled_shouldReturnUninstalled() {
assertThat(Utils.getInstallationStatus(new ApplicationInfo()))
.isEqualTo(R.string.not_installed);
}
@Test
- public void getInstallationStatus_enabled_shouldReturnInstalled() {
+ public void testGetInstallationStatus_enabled_shouldReturnInstalled() {
final ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_INSTALLED;
info.enabled = true;
@@ -134,7 +159,7 @@
}
@Test
- public void getInstallationStatus_disabled_shouldReturnDisabled() {
+ public void testGetInstallationStatus_disabled_shouldReturnDisabled() {
final ApplicationInfo info = new ApplicationInfo();
info.flags = ApplicationInfo.FLAG_INSTALLED;
info.enabled = false;
diff --git a/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
index 26c640d..c159a24 100644
--- a/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accounts/AccountSyncPreferenceControllerTest.java
@@ -15,11 +15,16 @@
*/
package com.android.settings.accounts;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
import android.accounts.Account;
import android.content.Context;
+import android.content.Intent;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
+import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@@ -29,9 +34,6 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
-import static org.mockito.Mockito.mock;
-import static com.google.common.truth.Truth.assertThat;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AccountSyncPreferenceControllerTest {
@@ -42,13 +44,18 @@
final Context context = application.getApplicationContext();
final Preference preference = new Preference(context);
preference.setKey("account_sync");
- AccountSyncPreferenceController controller = new AccountSyncPreferenceController(context);
- controller.init(new Account("acct1", "type1"), mock(UserHandle.class));
+ final AccountSyncPreferenceController controller =
+ new AccountSyncPreferenceController(context);
+ controller.init(new Account("acct1", "type1"), mock(UserHandle.class));
controller.handlePreferenceTreeClick(preference);
- assertThat(application.getNextStartedActivity().getStringExtra(
- SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(AccountSyncSettings.class.getName());
+ final Intent nextActivity = application.getNextStartedActivity();
+
+ assertThat(nextActivity.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
+ .isEqualTo(AccountSyncSettings.class.getName());
+ assertThat(nextActivity.getIntExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, 0))
+ .isEqualTo(R.string.account_sync_title);
}
}
diff --git a/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java
index 127100f..36d78c1 100644
--- a/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppStorageSizesControllerTest.java
@@ -110,4 +110,22 @@
assertThat(mDataPreference.getSummary()).isEqualTo("100B");
assertThat(mTotalPreference.getSummary()).isEqualTo("101B");
}
+
+ @Test
+ public void fakeDataFlagSetsDataAndCacheToZero() {
+ AppStorageStats result = mock(AppStorageStats.class);
+ when(result.getCodeBytes()).thenReturn(1L);
+ when(result.getCacheBytes()).thenReturn(10L);
+ when(result.getDataBytes()).thenReturn(100L);
+ when(result.getTotalBytes()).thenReturn(111L);
+
+ mController.setResult(result);
+ mController.setDataCleared(true);
+ mController.updateUi(mContext);
+
+ assertThat(mAppPreference.getSummary()).isEqualTo("1.00B");
+ assertThat(mCachePreference.getSummary()).isEqualTo("0.00B");
+ assertThat(mDataPreference.getSummary()).isEqualTo("0.00B");
+ assertThat(mTotalPreference.getSummary()).isEqualTo("1.00B");
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
index f372836..6cf4a59 100644
--- a/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/InstalledAppDetailsTest.java
@@ -18,7 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
@@ -69,6 +68,9 @@
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public final class InstalledAppDetailsTest {
+
+ private static final String PACKAGE_NAME = "test_package_name";
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
@@ -87,6 +89,8 @@
private BatteryStatsHelper mBatteryStatsHelper;
@Mock
private BatteryStats.Uid mUid;
+ @Mock
+ private PackageManager mPackageManager;
private InstalledAppDetails mAppDetail;
private Context mShadowContext;
@@ -94,14 +98,15 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mShadowContext = RuntimeEnvironment.application;
+ 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();
+ doReturn(mPackageManager).when(mActivity).getPackageManager();
// Default to not considering any apps to be instant (individual tests can override this).
ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
@@ -179,6 +184,24 @@
}
@Test
+ public void packageSizeChange_isOtherPackage_shouldNotRefreshUi() {
+ ReflectionHelpers.setField(mAppDetail, "mPackageName", PACKAGE_NAME);
+ mAppDetail.onPackageSizeChanged("Not_" + PACKAGE_NAME);
+
+ verify(mAppDetail, never()).refreshUi();
+ }
+
+ @Test
+ public void packageSizeChange_isOwnPackage_shouldRefreshUi() {
+ doReturn(Boolean.TRUE).when(mAppDetail).refreshUi();
+ ReflectionHelpers.setField(mAppDetail, "mPackageName", PACKAGE_NAME);
+
+ mAppDetail.onPackageSizeChanged(PACKAGE_NAME);
+
+ verify(mAppDetail).refreshUi();
+ }
+
+ @Test
public void launchPowerUsageDetailFragment_shouldNotCrash() {
mAppDetail.mBatteryPreference = mBatteryPreference;
mAppDetail.mSipper = mBatterySipper;
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryUpdaterTest.java
index cc059ad..79daa0e 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothSummaryUpdaterTest.java
@@ -16,7 +16,10 @@
package com.android.settings.bluetooth;
+import static com.google.common.truth.Truth.assertThat;
+
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import com.android.settings.R;
@@ -35,29 +38,38 @@
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowBluetoothAdapter;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class BluetoothSummaryUpdaterTest {
+ private static final String DEVICE_NAME = "Nightshade";
+ private static final String DEVICE_KEYBOARD_NAME = "Bluetooth Keyboard";
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private LocalBluetoothManager mBluetoothManager;
@Mock
private LocalBluetoothAdapter mBtAdapter;
-
- private BluetoothSummaryUpdater mSummaryUpdater;
+ @Mock
+ private BluetoothDevice mConnectedDevice;
+ @Mock
+ private BluetoothDevice mConnectedKeyBoardDevice;
@Mock
private SummaryListener mListener;
+ private BluetoothSummaryUpdater mSummaryUpdater;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -84,10 +96,12 @@
@Test
public void register_true_shouldSendSummaryChange() {
+ prepareConnectedDevice(false);
+
mSummaryUpdater.register(true);
verify(mListener).onSummaryChanged(
- mContext.getString(R.string.bluetooth_connected_summary));
+ mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
}
@Test
@@ -100,11 +114,13 @@
@Test
public void onBluetoothStateChanged_btEnabled_connected_shouldSendConnectedSummary() {
+ prepareConnectedDevice(false);
+
mSummaryUpdater.register(true);
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_ON);
verify(mListener).onSummaryChanged(
- mContext.getString(R.string.bluetooth_connected_summary));
+ mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
}
@Test
@@ -114,7 +130,7 @@
mSummaryUpdater.onBluetoothStateChanged(BluetoothAdapter.STATE_TURNING_ON);
verify(mListener).onSummaryChanged(
- mContext.getString(R.string.disconnected));
+ mContext.getString(R.string.disconnected));
}
@Test
@@ -123,26 +139,28 @@
devices.add(mock(CachedBluetoothDevice.class));
when(devices.get(0).isConnected()).thenReturn(true);
when(mBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy())
- .thenReturn(devices);
+ .thenReturn(devices);
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTED);
+ prepareConnectedDevice(false);
+
mSummaryUpdater.register(true);
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTED);
mSummaryUpdater.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_CONNECTED);
+ BluetoothAdapter.STATE_CONNECTED);
verify(mListener).onSummaryChanged(
- mContext.getString(R.string.bluetooth_connected_summary));
+ mContext.getString(R.string.bluetooth_connected_summary, DEVICE_NAME));
}
@Test
public void onConnectionStateChanged_inconsistentState_shouldSendDisconnectedMessage() {
mSummaryUpdater.register(true);
mSummaryUpdater.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_CONNECTED);
+ BluetoothAdapter.STATE_CONNECTED);
verify(mListener).onSummaryChanged(
- mContext.getString(R.string.disconnected));
+ mContext.getString(R.string.disconnected));
}
@Test
@@ -150,7 +168,7 @@
mSummaryUpdater.register(true);
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_CONNECTING);
mSummaryUpdater.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_CONNECTING);
+ BluetoothAdapter.STATE_CONNECTING);
verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_connecting));
}
@@ -160,11 +178,44 @@
mSummaryUpdater.register(true);
when(mBtAdapter.getConnectionState()).thenReturn(BluetoothAdapter.STATE_DISCONNECTING);
mSummaryUpdater.onConnectionStateChanged(null /* device */,
- BluetoothAdapter.STATE_DISCONNECTING);
+ BluetoothAdapter.STATE_DISCONNECTING);
verify(mListener).onSummaryChanged(mContext.getString(R.string.bluetooth_disconnecting));
}
+ @Test
+ public void getConnectedDeviceSummary_hasConnectedDevice_returnOneDeviceSummary() {
+ prepareConnectedDevice(false);
+ final String expectedSummary = mContext.getString(R.string.bluetooth_connected_summary,
+ DEVICE_NAME);
+
+ assertThat(mSummaryUpdater.getConnectedDeviceSummary()).isEqualTo(expectedSummary);
+ }
+
+ @Test
+ public void getConnectedDeviceSummary_multipleDevices_returnMultipleDevicesSummary() {
+ prepareConnectedDevice(true);
+ final String expectedSummary = mContext.getString(
+ R.string.bluetooth_connected_multiple_devices_summary);
+
+ assertThat(mSummaryUpdater.getConnectedDeviceSummary()).isEqualTo(expectedSummary);
+ }
+
+ private void prepareConnectedDevice(boolean multipleDevices) {
+ final Set<BluetoothDevice> devices = new HashSet<>();
+ doReturn(DEVICE_NAME).when(mConnectedDevice).getName();
+ doReturn(true).when(mConnectedDevice).isConnected();
+ devices.add(mConnectedDevice);
+ if (multipleDevices) {
+ // Add one more device if we need to test multiple devices
+ doReturn(DEVICE_KEYBOARD_NAME).when(mConnectedKeyBoardDevice).getName();
+ doReturn(true).when(mConnectedKeyBoardDevice).isConnected();
+ devices.add(mConnectedKeyBoardDevice);
+ }
+
+ doReturn(devices).when(mBtAdapter).getBondedDevices();
+ }
+
private class SummaryListener implements OnSummaryChangeListener {
String summary;
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
index fc4b75f..a4b5c97 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragmentTest.java
@@ -15,8 +15,12 @@
*/
package com.android.settings.connecteddevice;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.provider.SearchIndexableResource;
+import com.android.settings.bluetooth.BluetoothMasterSwitchPreferenceController;
+import com.android.settings.nfc.NfcPreferenceController;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settingslib.drawer.CategoryKey;
@@ -24,22 +28,33 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import java.util.List;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ConnectedDeviceDashboardFragmentTest {
+ @Mock
+ Context mContext;
+
+ @Mock
+ private PackageManager mManager;
private ConnectedDeviceDashboardFragment mFragment;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mFragment = new ConnectedDeviceDashboardFragment();
+ when(mContext.getPackageManager()).thenReturn(mManager);
}
@Test
@@ -50,11 +65,47 @@
@Test
public void testSearchIndexProvider_shouldIndexResource() {
final List<SearchIndexableResource> indexRes =
- ConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
- ShadowApplication.getInstance().getApplicationContext(),
- true /* enabled */);
+ mFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(mContext, true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
}
+
+ @Test
+ public void testSearchIndexProvider_NoNfc_KeyAdded() {
+ when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(false);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(keys).isNotNull();
+ assertThat(keys).contains(NfcPreferenceController.KEY_TOGGLE_NFC);
+ assertThat(keys).contains(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
+ }
+
+ @Test
+ public void testSearchIndexProvider_NFC_KeyNotAdded() {
+ when(mManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(true);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(keys).isNotNull();
+ assertThat(keys).doesNotContain(NfcPreferenceController.KEY_TOGGLE_NFC);
+ assertThat(keys).doesNotContain(NfcPreferenceController.KEY_ANDROID_BEAM_SETTINGS);
+ }
+
+ @Test
+ public void testSearchIndexProvider_NoBluetooth_KeyAdded() {
+ when(mManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(false);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(keys).isNotNull();
+ assertThat(keys).contains(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
+ }
+
+ @Test
+ public void testSearchIndexProvider_Bluetooth_KeyNotAdded() {
+ when(mManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)).thenReturn(true);
+ final List<String> keys = mFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(keys).isNotNull();
+ assertThat(keys).doesNotContain(BluetoothMasterSwitchPreferenceController.KEY_TOGGLE_BLUETOOTH);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
index 72231b2..accca2a 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionsChecksTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Google Inc.
+ * 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.
@@ -17,12 +17,12 @@
package com.android.settings.dashboard.suggestions;
import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
+import android.app.WallpaperManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
@@ -41,6 +41,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -54,7 +56,8 @@
private FingerprintManager mFingerprintManager;
@Mock
private DevicePolicyManager mDevicePolicyManager;
-
+ @Mock
+ private WallpaperManagerWrapper mWallpaperManager;
private SuggestionsChecks mSuggestionsChecks;
@Before
@@ -118,4 +121,24 @@
Settings.FingerprintEnrollSuggestionActivity.class));
return tile;
}
+
+ @Test
+ public void hasWallpaperSet_no_shouldReturnFalse() {
+ ReflectionHelpers.setField(mSuggestionsChecks, "mWallpaperManager", mWallpaperManager);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM))
+ .thenReturn(0);
+
+ assertThat(mSuggestionsChecks.hasWallpaperSet())
+ .isFalse();
+ }
+
+ @Test
+ public void hasWallpaperSet_yes_shouldReturnTrue() {
+ ReflectionHelpers.setField(mSuggestionsChecks, "mWallpaperManager", mWallpaperManager);
+ when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM))
+ .thenReturn(100);
+
+ assertThat(mSuggestionsChecks.hasWallpaperSet())
+ .isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
index 47d910d..efe44ef 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/StorageItemPreferenceControllerTest.java
@@ -84,7 +84,7 @@
FakeFeatureFactory.setupForTest(mContext);
mFakeFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
mMetricsFeatureProvider = mFakeFeatureFactory.getMetricsFeatureProvider();
- mVolume = new VolumeInfo("id", 0, null, "id");
+ mVolume = spy(new VolumeInfo("id", 0, null, "id"));
// Note: null is passed as the Lifecycle because we are handling it outside of the normal
// Settings fragment lifecycle for test purposes.
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp);
@@ -305,4 +305,90 @@
verify(system, times(2)).setIcon(any(Drawable.class));
verify(files, times(2)).setIcon(any(Drawable.class));
}
+
+ @Test
+ public void displayPreference_dontHideFilePreferenceWhenEmulatedInternalStorageUsed() {
+ StorageItemPreference audio = new StorageItemPreference(mContext);
+ StorageItemPreference image = new StorageItemPreference(mContext);
+ StorageItemPreference games = new StorageItemPreference(mContext);
+ StorageItemPreference apps = new StorageItemPreference(mContext);
+ StorageItemPreference system = new StorageItemPreference(mContext);
+ StorageItemPreference files = new StorageItemPreference(mContext);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
+ .thenReturn(audio);
+ when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
+ .thenReturn(image);
+ when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+ when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
+ .thenReturn(apps);
+ when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
+ .thenReturn(system);
+ when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
+ .thenReturn(files);
+
+ when(mSvp.findEmulatedForPrivate(any(VolumeInfo.class))).thenReturn(mVolume);
+ when(mVolume.isMountedReadable()).thenReturn(true);
+
+ mController.displayPreference(screen);
+
+ verify(screen, times(0)).removePreference(files);
+ }
+
+ @Test
+ public void displayPreference_hideFilePreferenceWhenEmulatedStorageUnreadable() {
+ StorageItemPreference audio = new StorageItemPreference(mContext);
+ StorageItemPreference image = new StorageItemPreference(mContext);
+ StorageItemPreference games = new StorageItemPreference(mContext);
+ StorageItemPreference apps = new StorageItemPreference(mContext);
+ StorageItemPreference system = new StorageItemPreference(mContext);
+ StorageItemPreference files = new StorageItemPreference(mContext);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
+ .thenReturn(audio);
+ when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
+ .thenReturn(image);
+ when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+ when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
+ .thenReturn(apps);
+ when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
+ .thenReturn(system);
+ when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
+ .thenReturn(files);
+
+ when(mSvp.findEmulatedForPrivate(any(VolumeInfo.class))).thenReturn(mVolume);
+ when(mVolume.isMountedReadable()).thenReturn(false);
+
+ mController.displayPreference(screen);
+
+ verify(screen).removePreference(files);
+ }
+
+ @Test
+ public void displayPreference_hideFilePreferenceWhenNoEmulatedInternalStorage() {
+ StorageItemPreference audio = new StorageItemPreference(mContext);
+ StorageItemPreference image = new StorageItemPreference(mContext);
+ StorageItemPreference games = new StorageItemPreference(mContext);
+ StorageItemPreference apps = new StorageItemPreference(mContext);
+ StorageItemPreference system = new StorageItemPreference(mContext);
+ StorageItemPreference files = new StorageItemPreference(mContext);
+ PreferenceScreen screen = mock(PreferenceScreen.class);
+ when(screen.findPreference(eq(StorageItemPreferenceController.AUDIO_KEY)))
+ .thenReturn(audio);
+ when(screen.findPreference(eq(StorageItemPreferenceController.PHOTO_KEY)))
+ .thenReturn(image);
+ when(screen.findPreference(eq(StorageItemPreferenceController.GAME_KEY))).thenReturn(games);
+ when(screen.findPreference(eq(StorageItemPreferenceController.OTHER_APPS_KEY)))
+ .thenReturn(apps);
+ when(screen.findPreference(eq(StorageItemPreferenceController.SYSTEM_KEY)))
+ .thenReturn(system);
+ when(screen.findPreference(eq(StorageItemPreferenceController.FILES_KEY)))
+ .thenReturn(files);
+
+ when(mSvp.findEmulatedForPrivate(any(VolumeInfo.class))).thenReturn(null);
+
+ mController.displayPreference(screen);
+
+ verify(screen).removePreference(files);
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index 15fec3c..4305dc7 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -57,6 +57,8 @@
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.robolectric.RuntimeEnvironment;
+
import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@@ -143,6 +145,7 @@
mFragment.mHeaderPreference = mHeaderPreference;
mFragment.mState = mState;
+ mFragment.mBatteryUtils = new BatteryUtils(RuntimeEnvironment.application);
mAppEntry.info = mock(ApplicationInfo.class);
mTestActivity = spy(new SettingsActivity());
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryStatsHelperLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryStatsHelperLoaderTest.java
new file mode 100644
index 0000000..d19a4b2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryStatsHelperLoaderTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.BatteryStats;
+import android.os.Bundle;
+import android.os.UserManager;
+
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BatteryStatsHelperLoaderTest {
+ @Mock
+ private BatteryStatsHelper mBatteryStatsHelper;
+ @Mock
+ private Bundle mBundle;
+ @Mock
+ private Context mContext;
+ @Mock
+ private UserManager mUserManager;
+ private BatteryStatsHelperLoader mLoader;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mLoader = new BatteryStatsHelperLoader(mContext, mBundle);
+ mLoader.mUserManager = mUserManager;
+ }
+
+ @Test
+ public void testInitBatteryStatsHelper_init() {
+ mLoader.initBatteryStatsHelper(mBatteryStatsHelper);
+
+ verify(mBatteryStatsHelper).create(mBundle);
+ verify(mBatteryStatsHelper).refreshStats(BatteryStats.STATS_SINCE_CHARGED,
+ mUserManager.getUserProfiles());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index e5383c8..f9cc771 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -33,6 +33,9 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.ArrayList;
+import java.util.List;
+
import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND;
import static android.os.BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE;
@@ -47,9 +50,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
+import static org.mockito.Mockito.spy;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -63,12 +64,13 @@
private static final long TIME_STATE_BACKGROUND = 6000 * UNIT;
private static final int UID = 123;
- private static final long TIME_EXPECTED_FOREGROUND = 9000;
+ private static final long TIME_EXPECTED_FOREGROUND = 6500;
private static final long TIME_EXPECTED_BACKGROUND = 6000;
- private static final long TIME_EXPECTED_ALL = 15000;
+ private static final long TIME_EXPECTED_ALL = 12500;
private static final double BATTERY_SCREEN_USAGE = 300;
private static final double BATTERY_SYSTEM_USAGE = 600;
private static final double BATTERY_OVERACCOUNTED_USAGE = 500;
+ private static final double BATTERY_UNACCOUNTED_USAGE = 700;
private static final double TOTAL_BATTERY_USAGE = 1000;
private static final double HIDDEN_USAGE = 200;
private static final int DISCHARGE_AMOUNT = 80;
@@ -84,6 +86,8 @@
@Mock
private BatterySipper mOvercountedBatterySipper;
@Mock
+ private BatterySipper mUnaccountedBatterySipper;
+ @Mock
private BatterySipper mSystemBatterySipper;
@Mock
private BatterySipper mCellBatterySipper;
@@ -125,8 +129,13 @@
mOvercountedBatterySipper.drainType = BatterySipper.DrainType.OVERCOUNTED;
mOvercountedBatterySipper.totalPowerMah = BATTERY_OVERACCOUNTED_USAGE;
+ mUnaccountedBatterySipper.drainType = BatterySipper.DrainType.UNACCOUNTED;
+ mUnaccountedBatterySipper.totalPowerMah = BATTERY_UNACCOUNTED_USAGE;
+
mBatteryUtils = BatteryUtils.getInstance(RuntimeEnvironment.application);
mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
+
+ mBatteryUtils = spy(new BatteryUtils(RuntimeEnvironment.application));
}
@Test
@@ -168,12 +177,14 @@
sippers.add(mScreenBatterySipper);
sippers.add(mSystemBatterySipper);
sippers.add(mOvercountedBatterySipper);
+ sippers.add(mUnaccountedBatterySipper);
when(mProvider.isTypeSystem(mSystemBatterySipper))
.thenReturn(true);
final double totalUsage = mBatteryUtils.removeHiddenBatterySippers(sippers);
assertThat(sippers).containsExactly(mNormalBatterySipper);
- assertThat(totalUsage).isWithin(PRECISION).of(BATTERY_SCREEN_USAGE + BATTERY_SYSTEM_USAGE);
+ assertThat(totalUsage).isWithin(PRECISION).of(
+ BATTERY_SCREEN_USAGE + BATTERY_SYSTEM_USAGE + BATTERY_UNACCOUNTED_USAGE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
index 41b1c96..d46baa1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserManager;
+import android.text.TextUtils;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatterySipper.DrainType;
@@ -105,9 +106,12 @@
when(mPowerUsageAdvanced.getContext()).thenReturn(mShadowContext);
doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any(), any());
doReturn(STUB_STRING).when(mPowerUsageAdvanced).getString(anyInt(), any());
+ doReturn(mShadowContext.getText(R.string.battery_used_for)).when(
+ mPowerUsageAdvanced).getText(R.string.battery_used_for);
mPowerUsageAdvanced.setPackageManager(mPackageManager);
mPowerUsageAdvanced.setPowerUsageFeatureProvider(mPowerUsageFeatureProvider);
mPowerUsageAdvanced.setUserManager(mUserManager);
+ mPowerUsageAdvanced.setBatteryUtils(BatteryUtils.getInstance(mShadowContext));
mPowerUsageData = new PowerUsageData(UsageType.APP);
mMaxBatterySipper.totalPowerMah = TYPE_BLUETOOTH_USAGE;
@@ -176,10 +180,12 @@
@Test
public void testUpdateUsageDataSummary_onlyOneApp_showUsageTime() {
+ final String expectedSummary = "Used for 0m";
mPowerUsageData.usageList.add(mNormalBatterySipper);
+
mPowerUsageAdvanced.updateUsageDataSummary(mPowerUsageData, TOTAL_POWER, DISCHARGE_AMOUNT);
- verify(mPowerUsageAdvanced).getString(eq(R.string.battery_used_for), any());
+ assertThat(mPowerUsageData.summary.toString()).isEqualTo(expectedSummary);
}
@Test
@@ -293,4 +299,16 @@
assertThat(mPowerUsageAdvanced.shouldShowBatterySipper(mNormalBatterySipper)).isTrue();
}
+ @Test
+ public void testCalculateHiddenPower_returnCorrectPower() {
+ List<PowerUsageData> powerUsageDataList = new ArrayList<>();
+ final double unaccountedPower = 100;
+ final double normalPower = 150;
+ powerUsageDataList.add(new PowerUsageData(UsageType.UNACCOUNTED, unaccountedPower));
+ powerUsageDataList.add(new PowerUsageData(UsageType.APP, normalPower));
+ powerUsageDataList.add(new PowerUsageData(UsageType.CELL, normalPower));
+
+ assertThat(mPowerUsageAdvanced.calculateHiddenPower(powerUsageDataList)).isWithin(
+ PRECISION).of(unaccountedPower);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 5611371..3556d09 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -88,15 +88,16 @@
public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
private static final String TIME_LEFT = "2h30min";
+ private static final String STUB_STRING = "stub_string";
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_MS = 120 * 60 * 1000;
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 long USAGE_TIME_MS = 65 * 60 * 1000;
private static final double TOTAL_POWER = 200;
private static final double BATTERY_SCREEN_USAGE = 300;
private static final double BATTERY_SYSTEM_USAGE = 600;
@@ -125,8 +126,6 @@
@Mock
private BatterySipper mCellBatterySipper;
@Mock
- private PowerGaugePreference mPreference;
- @Mock
private LayoutPreference mBatteryLayoutPref;
@Mock
private TextView mBatteryPercentText;
@@ -134,10 +133,6 @@
private TextView mSummary1;
@Mock
private BatteryInfo mBatteryInfo;
- @Mock
- private PowerGaugePreference mScreenUsagePref;
- @Mock
- private PowerGaugePreference mLastFullChargePref;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private BatteryStatsHelper mBatteryHelper;
@Mock
@@ -150,6 +145,9 @@
private TestFragment mFragment;
private FakeFeatureFactory mFeatureFactory;
private BatteryMeterView mBatteryMeterView;
+ private PowerGaugePreference mPreference;
+ private PowerGaugePreference mScreenUsagePref;
+ private PowerGaugePreference mLastFullChargePref;
@Before
public void setUp() {
@@ -160,6 +158,9 @@
mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
+ mPreference = new PowerGaugePreference(mRealContext);
+ mScreenUsagePref = new PowerGaugePreference(mRealContext);
+ mLastFullChargePref = new PowerGaugePreference(mRealContext);
mFragment = spy(new TestFragment(mContext));
mFragment.initFeatureProvider();
mBatteryMeterView = new BatteryMeterView(mRealContext);
@@ -202,6 +203,7 @@
when(mBatteryHelper.getUsageList()).thenReturn(mUsageList);
mFragment.mScreenUsagePref = mScreenUsagePref;
mFragment.mLastFullChargePref = mLastFullChargePref;
+ mFragment.mBatteryUtils = spy(new BatteryUtils(mRealContext));
mBatteryInfo.batteryLevel = BATTERY_LEVEL;
}
@@ -306,16 +308,21 @@
public void testSetUsageSummary_timeLessThanOneMinute_DoNotSetSummary() {
final long usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS;
- mFragment.setUsageSummary(mPreference, "", usageTimeMs);
- verify(mPreference, never()).setSummary(anyString());
+ mFragment.setUsageSummary(mPreference, usageTimeMs);
+ assertThat(mPreference.getSummary()).isNull();
}
@Test
public void testSetUsageSummary_timeMoreThanOneMinute_setSummary() {
final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
+ doReturn(mRealContext.getText(R.string.battery_used_for)).when(mFragment).getText(
+ R.string.battery_used_for);
+ doReturn(mRealContext).when(mFragment).getContext();
+ final String expectedSummary = "Used for 2m";
- mFragment.setUsageSummary(mPreference, "", usageTimeMs);
- verify(mPreference).setSummary(anyString());
+ mFragment.setUsageSummary(mPreference, usageTimeMs);
+
+ assertThat(mPreference.getSummary().toString()).isEqualTo(expectedSummary);
}
@Test
@@ -382,32 +389,37 @@
@Test
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();
+ final CharSequence expectedSummary = Utils.formatElapsedTime(mRealContext, USAGE_TIME_MS,
+ false);
mFragment.updateScreenPreference();
- verify(mScreenUsagePref).setSubtitle(expectedUsedTime);
+ assertThat(mScreenUsagePref.getSubtitle()).isEqualTo(expectedSummary);
}
@Test
public void testUpdateLastFullChargePreference_showCorrectSummary() {
+ final CharSequence formattedString = mRealContext.getText(
+ R.string.power_last_full_charge_summary);
+ final CharSequence timeSequence = Utils.formatElapsedTime(mRealContext,
+ TIME_SINCE_LAST_FULL_CHARGE_MS, false);
+ final CharSequence expectedSummary = TextUtils.expandTemplate(
+ formattedString, timeSequence);
+ doReturn(formattedString).when(mFragment).getText(R.string.power_last_full_charge_summary);
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.updateLastFullChargePreference(TIME_SINCE_LAST_FULL_CHARGE_MS);
- verify(mLastFullChargePref).setSubtitle(expected);
+ assertThat(mLastFullChargePref.getSubtitle()).isEqualTo(expectedSummary);
}
@Test
public void testUpdatePreference_usageListEmpty_shouldNotCrash() {
when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList<BatterySipper>());
- doReturn("").when(mFragment).getString(anyInt(), any());
+ doReturn(STUB_STRING).when(mFragment).getString(anyInt(), any());
+ doReturn(mRealContext).when(mFragment).getContext();
// Should not crash when update
mFragment.updateScreenPreference();
@@ -474,7 +486,7 @@
}
@Override
- protected void refreshStats() {
+ protected void refreshUi() {
// Leave it empty for toggle apps menu test
}
}
diff --git a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java b/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java
index 647d68c..645dfe5 100644
--- a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java
@@ -63,6 +63,8 @@
private Context mContext;
private String mLoaderClassName;
+ private String[] TITLES = {"alpha", "bravo", "charlie", "appAlpha", "appBravo", "appCharlie"};
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -72,13 +74,13 @@
}
@Test
- public void testNoResultsAdded_EmptyListReturned() {
+ public void testNoResultsAdded_emptyListReturned() {
List<SearchResult> updatedResults = mAdapter.getSearchResults();
assertThat(updatedResults).isEmpty();
}
@Test
- public void testSingleSourceMerge_ExactCopyReturned() {
+ public void testSingleSourceMerge_exactCopyReturned() {
ArrayList<SearchResult> intentResults = getIntentSampleResults();
mAdapter.addSearchResults(intentResults, mLoaderClassName);
mAdapter.displaySearchResults();
@@ -88,7 +90,7 @@
}
@Test
- public void testCreateViewHolder_ReturnsIntentResult() {
+ public void testCreateViewHolder_returnsIntentResult() {
ViewGroup group = new FrameLayout(mContext);
SearchViewHolder view = mAdapter.onCreateViewHolder(group,
ResultPayload.PayloadType.INTENT);
@@ -96,7 +98,7 @@
}
@Test
- public void testCreateViewHolder_ReturnsInlineSwitchResult() {
+ public void testCreateViewHolder_returnsInlineSwitchResult() {
ViewGroup group = new FrameLayout(mContext);
SearchViewHolder view = mAdapter.onCreateViewHolder(group,
ResultPayload.PayloadType.INLINE_SWITCH);
@@ -104,21 +106,54 @@
}
@Test
- public void testEndToEndSearch_ProperResultsMerged() {
- mAdapter.addSearchResults(getDummyAppResults(),
+ public void testEndToEndSearch_properResultsMerged_correctOrder() {
+ mAdapter.addSearchResults(getDummyAppResults(), InstalledAppResultLoader.class.getName());
+ mAdapter.addSearchResults(getDummyDbResults(), DatabaseResultLoader.class.getName());
+ mAdapter.displaySearchResults();
+
+ List<SearchResult> results = mAdapter.getSearchResults();
+ List<SearchResult> sortedDummyResults = getSortedDummyResults();
+
+ assertThat(results).containsExactlyElementsIn(sortedDummyResults).inOrder();
+ }
+
+ @Test
+ public void testEndToEndSearch_addResults_resultsAddedInOrder() {
+ List<AppSearchResult> appResults = getDummyAppResults();
+ List<SearchResult> dbResults = getDummyDbResults();
+ // Add two individual items
+ mAdapter.addSearchResults(appResults.subList(0,1),
InstalledAppResultLoader.class.getName());
- mAdapter.addSearchResults(getDummyDbResults(),
- DatabaseResultLoader.class.getName());
+ mAdapter.addSearchResults(dbResults.subList(0,1), DatabaseResultLoader.class.getName());
+ mAdapter.displaySearchResults();
+ // Add super-set of items
+ mAdapter.addSearchResults(appResults, InstalledAppResultLoader.class.getName());
+ mAdapter.addSearchResults(dbResults, DatabaseResultLoader.class.getName());
+ mAdapter.displaySearchResults();
+
+ List<SearchResult> results = mAdapter.getSearchResults();
+ List<SearchResult> sortedDummyResults = getSortedDummyResults();
+ assertThat(results).containsExactlyElementsIn(sortedDummyResults).inOrder();
+ }
+
+ @Test
+ public void testEndToEndSearch_removeResults_resultsAdded() {
+ List<AppSearchResult> appResults = getDummyAppResults();
+ List<SearchResult> dbResults = getDummyDbResults();
+ // Add list of items
+ mAdapter.addSearchResults(appResults, InstalledAppResultLoader.class.getName());
+ mAdapter.addSearchResults(dbResults, DatabaseResultLoader.class.getName());
+ mAdapter.displaySearchResults();
+ // Add subset of items
+ mAdapter.addSearchResults(appResults.subList(0,1),
+ InstalledAppResultLoader.class.getName());
+ mAdapter.addSearchResults(dbResults.subList(0,1), DatabaseResultLoader.class.getName());
int count = mAdapter.displaySearchResults();
List<SearchResult> results = mAdapter.getSearchResults();
- assertThat(results.get(0).title).isEqualTo("alpha");
- assertThat(results.get(1).title).isEqualTo("appAlpha");
- assertThat(results.get(2).title).isEqualTo("appBravo");
- assertThat(results.get(3).title).isEqualTo("bravo");
- assertThat(results.get(4).title).isEqualTo("appCharlie");
- assertThat(results.get(5).title).isEqualTo("Charlie");
- assertThat(count).isEqualTo(6);
+ assertThat(results.get(0).title).isEqualTo(TITLES[0]);
+ assertThat(results.get(1).title).isEqualTo(TITLES[3]);
+ assertThat(count).isEqualTo(2);
}
private List<SearchResult> getDummyDbResults() {
@@ -127,15 +162,15 @@
SearchResult.Builder builder = new SearchResult.Builder();
builder.addPayload(payload);
- builder.addTitle("alpha")
+ builder.addTitle(TITLES[0])
.addRank(1);
results.add(builder.build());
- builder.addTitle("bravo")
+ builder.addTitle(TITLES[1])
.addRank(3);
results.add(builder.build());
- builder.addTitle("Charlie")
+ builder.addTitle(TITLES[2])
.addRank(6);
results.add(builder.build());
@@ -148,21 +183,35 @@
AppSearchResult.Builder builder = new AppSearchResult.Builder();
builder.addPayload(payload);
- builder.addTitle("appAlpha")
+ builder.addTitle(TITLES[3])
.addRank(1);
results.add(builder.build());
- builder.addTitle("appBravo")
+ builder.addTitle(TITLES[4])
.addRank(2);
results.add(builder.build());
- builder.addTitle("appCharlie")
+ builder.addTitle(TITLES[5])
.addRank(4);
results.add(builder.build());
return results;
}
+ private List<SearchResult> getSortedDummyResults() {
+ List<AppSearchResult> appResults = getDummyAppResults();
+ List<SearchResult> dbResults = getDummyDbResults();
+ List<SearchResult> sortedResults = new ArrayList<>(appResults.size() + dbResults.size());
+ sortedResults.add(dbResults.get(0)); // alpha
+ sortedResults.add(appResults.get(0)); // appAlpha
+ sortedResults.add(appResults.get(1)); // appBravo
+ sortedResults.add(dbResults.get(1)); // bravo
+ sortedResults.add(appResults.get(2)); // appCharlie
+ sortedResults.add(dbResults.get(2)); // Charlie
+
+ return sortedResults;
+ }
+
private ArrayList<SearchResult> getIntentSampleResults() {
ArrayList<SearchResult> sampleResults = new ArrayList<>();
ArrayList<String> breadcrumbs = new ArrayList<>();
diff --git a/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java b/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java
index aa4e4f9..047d867 100644
--- a/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java
+++ b/tests/robotests/src/com/android/settings/search2/DatabaseIndexingManagerTest.java
@@ -303,7 +303,7 @@
// Class Name
assertThat(cursor.getString(11)).isEqualTo(className);
// Icon
- assertThat(cursor.getInt(12)).isEqualTo(iconResId);
+ assertThat(cursor.getInt(12)).isEqualTo(0);
// Intent Action
assertThat(cursor.getString(13)).isEqualTo(action);
// Target Package
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java b/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java
new file mode 100644
index 0000000..4903b86
--- /dev/null
+++ b/tests/unit/src/com/android/settings/deviceinfo/PublicVolumeSettingsTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.deviceinfo;
+
+import android.content.Intent;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.settings.Settings;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PublicVolumeSettingsTest {
+ @Rule
+ public ActivityTestRule<Settings.PublicVolumeSettingsActivity> mActivityRule =
+ new ActivityTestRule<>(Settings.PublicVolumeSettingsActivity.class, true, true);
+
+ @Test
+ public void test_invalidSetupDoesNotCrashSettings() {
+ Intent intent = new Intent();
+ intent.setAction(android.provider.Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+ intent.setClassName(InstrumentationRegistry.getTargetContext().getPackageName(),
+ Settings.PublicVolumeSettingsActivity.class.getName());
+ mActivityRule.launchActivity(intent);
+
+ // Should exit gracefully without crashing.
+ }
+}