From ae4b79ee6dd45c1f45d13da7c604ec8ecceb4306 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Wed, 16 Aug 2017 14:34:56 -0700 Subject: [PATCH 1/6] Update strings when shortString is true After b/64124535, battery strings in settings page use shortString version. This cl updates the charging string in this situation to match the mock. Note that no matter whether we use shorString, the chargingLabel should remain the same. Bug: 64752046 Test: RunSettingsRoboTests Change-Id: I4395d4660e212688cd560ca0b124acbd9c099cc9 --- src/com/android/settings/fuelgauge/BatteryInfo.java | 3 +-- .../src/com/android/settings/fuelgauge/BatteryInfoTest.java | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/fuelgauge/BatteryInfo.java b/src/com/android/settings/fuelgauge/BatteryInfo.java index bcc23463d0a..7a0cd276369 100644 --- a/src/com/android/settings/fuelgauge/BatteryInfo.java +++ b/src/com/android/settings/fuelgauge/BatteryInfo.java @@ -243,8 +243,7 @@ public class BatteryInfo { info.remainingTimeUs = chargeTime; CharSequence timeString = Utils.formatElapsedTime(context, BatteryUtils.convertUsToMs(chargeTime), false /* withSeconds */); - int resId = shortString ? R.string.power_charging_duration_short - : R.string.power_charging_duration; + int resId = R.string.power_charging_duration; info.remainingLabel = TextUtils.expandTemplate(context.getText( R.string.power_remaining_charging_duration_only), timeString); info.chargeLabel = TextUtils.expandTemplate(context.getText(resId), diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java index 7392eb6379a..d82a89b5f93 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryInfoTest.java @@ -123,11 +123,14 @@ public class BatteryInfoTest { } @Test - public void testGetBatteryInfo_pluggedIn_dischargingFalse() { + public void testGetBatteryInfo_pluggedInUsingShortString_usesCorrectData() { + doReturn(TEST_CHARGE_TIME_REMAINING).when(mBatteryStats).computeChargeTimeRemaining( + anyLong()); BatteryInfo info = BatteryInfo.getBatteryInfoOld(mContext, mChargingBatteryBroadcast, mBatteryStats, SystemClock.elapsedRealtime() * 1000, true /* shortString */); assertThat(info.discharging).isEqualTo(false); + assertThat(info.chargeLabel.toString()).isEqualTo("50% - 1m until fully charged"); } @Test From 97da51876b67942fd412355fa8c6cac5b3f93eba Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Wed, 16 Aug 2017 12:40:01 -0700 Subject: [PATCH 2/6] Fix null pointer exception when logging suggestions. In monkey test, the suggestions list can become null. So, add check for valid suggestions list before trying to iterate through the suggestions. Fixes: 64757618 Test: make RunSettingsRoboTests Change-Id: Ib670808a4f222187b9cd53d7d939e71b5ce8dbae --- .../settings/dashboard/DashboardAdapter.java | 6 +++++- .../settings/dashboard/DashboardAdapterTest.java | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java index 2bf1c01f144..c06a58fe24c 100644 --- a/src/com/android/settings/dashboard/DashboardAdapter.java +++ b/src/com/android/settings/dashboard/DashboardAdapter.java @@ -329,7 +329,11 @@ public class DashboardAdapter extends RecyclerView.Adapter suggestions = mDashboardData.getSuggestions(); + if (suggestions == null) { + return; + } + for (Tile suggestion : suggestions) { final String suggestionId = mSuggestionFeatureProvider.getSuggestionIdentifier( mContext, suggestion); if (!mSuggestionsShownLogged.contains(suggestionId)) { diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java index 6b56c291324..e00908e52b3 100644 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java +++ b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java @@ -318,6 +318,21 @@ public class DashboardAdapterTest { assertThat(mActionCategoryCaptor.getAllValues().toArray()).isEqualTo(expectedActions); } + @Test + public void testSuggestionsLogs_nullSuggestionsList_shouldNotCrash() { + setupSuggestions(makeSuggestions("pkg1", "pkg2", "pkg3", "pkg4", "pkg5")); + mDashboardAdapter.onBindSuggestionConditionHeader(mSuggestionHolder, mSuggestionHeaderData); + + // set suggestions to null + final DashboardData prevData = mDashboardAdapter.mDashboardData; + mDashboardAdapter.mDashboardData = new DashboardData.Builder(prevData) + .setSuggestions(null) + .build(); + + mSuggestionHolder.itemView.callOnClick(); + // no crash + } + @Test public void testSuggestionDismissed_notOnlySuggestion_updateSuggestionOnly() { final DashboardAdapter adapter = From dc1add0c6142861d2b702e36cfb576e3ff52a3d0 Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Fri, 11 Aug 2017 13:09:35 -0700 Subject: [PATCH 3/6] Add a "Add Network" button to SavedAccessPointsWifiSettings Bug: 36719359 Test: runtest --path packages/apps/Settings/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java Test: Open saved networks from WifiSettings. Ensure that exiting and resuming the activity keeps the "Add Network" button on the bottom of the network list. This is tested through the cases where networks are forgotten/saved before resuming, and that pausing/resuming when the dialog is open or closed does not affect the result. Change-Id: Ib719a1f6b9468c0f8f44470eeed9144904672cf1 --- .../wifi/SavedAccessPointsWifiSettings.java | 53 +++++++++---- .../wifi/SavedNetworkSettingsTest.java | 76 +++++++++++++++++++ 2 files changed, 116 insertions(+), 13 deletions(-) create mode 100644 tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java diff --git a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java index 33fdf2d68f5..1a95525fe24 100644 --- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java +++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java @@ -16,13 +16,12 @@ package com.android.settings.wifi; +import android.annotation.Nullable; import android.app.Dialog; import android.content.Context; import android.content.res.Resources; import android.icu.text.Collator; -import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; -import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.Bundle; import android.provider.SearchIndexableResource; import android.support.v7.preference.Preference; @@ -48,6 +47,7 @@ import java.util.List; /** * UI to manage saved networks/access points. + * TODO(b/64806699): convert to {@link DashboardFragment} with {@link PreferenceController}s */ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment implements Indexable, WifiDialog.WifiDialogListener { @@ -83,6 +83,7 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment private AccessPoint mDlgAccessPoint; private Bundle mAccessPointSavedState; private AccessPoint mSelectedAccessPoint; + private Preference mAddNetworkPreference; private AccessPointPreference.UserBadgeCache mUserBadgeCache; @@ -142,23 +143,38 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment preference.setIcon(null); preferenceScreen.addPreference(preference); } + preference.setOrder(i); } removeCachedPrefs(preferenceScreen); + if (mAddNetworkPreference == null) { + mAddNetworkPreference = new Preference(getPrefContext()); + mAddNetworkPreference.setIcon(R.drawable.ic_menu_add_inset); + mAddNetworkPreference.setTitle(R.string.wifi_add_network); + } + mAddNetworkPreference.setOrder(accessPointsSize); + preferenceScreen.addPreference(mAddNetworkPreference); + if(getPreferenceScreen().getPreferenceCount() < 1) { Log.w(TAG, "Saved networks activity loaded, but there are no saved networks!"); } } - private void showDialog(LongPressAccessPointPreference accessPoint, boolean edit) { + private void showWifiDialog(@Nullable LongPressAccessPointPreference accessPoint) { if (mDialog != null) { removeDialog(WifiSettings.WIFI_DIALOG_ID); mDialog = null; } - // Save the access point and edit mode - mDlgAccessPoint = accessPoint.getAccessPoint(); + if (accessPoint != null) { + // Save the access point and edit mode + mDlgAccessPoint = accessPoint.getAccessPoint(); + } else { + // No access point is selected. Clear saved state. + mDlgAccessPoint = null; + mAccessPointSavedState = null; + } showDialog(WifiSettings.WIFI_DIALOG_ID); } @@ -167,15 +183,23 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment public Dialog onCreateDialog(int dialogId) { switch (dialogId) { case WifiSettings.WIFI_DIALOG_ID: - if (mDlgAccessPoint == null) { // For re-launch from saved state - mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); - // Reset the saved access point data - mAccessPointSavedState = null; + if (mDlgAccessPoint == null && mAccessPointSavedState == null) { + // Add new network + mDialog = WifiDialog.createFullscreen(getActivity(), this, null, + WifiConfigUiBase.MODE_CONNECT); + } else { + // Modify network + if (mDlgAccessPoint == null) { + // Restore AP from save state + mDlgAccessPoint = new AccessPoint(getActivity(), mAccessPointSavedState); + // Reset the saved access point data + mAccessPointSavedState = null; + } + mDialog = WifiDialog.createModal(getActivity(), this, mDlgAccessPoint, + WifiConfigUiBase.MODE_VIEW); } mSelectedAccessPoint = mDlgAccessPoint; - mDialog = WifiDialog.createModal(getActivity(), this, mDlgAccessPoint, - WifiConfigUiBase.MODE_VIEW); return mDialog; } return super.onCreateDialog(dialogId); @@ -233,9 +257,12 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment @Override public boolean onPreferenceTreeClick(Preference preference) { if (preference instanceof LongPressAccessPointPreference) { - showDialog((LongPressAccessPointPreference) preference, false); + showWifiDialog((LongPressAccessPointPreference) preference); return true; - } else{ + } else if (preference == mAddNetworkPreference) { + showWifiDialog(null); + return true; + } else { return super.onPreferenceTreeClick(preference); } } diff --git a/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java b/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java new file mode 100644 index 00000000000..79eccc4a87a --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/SavedNetworkSettingsTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.wifi; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import android.content.Context; +import android.content.Intent; +import android.support.test.InstrumentationRegistry; +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; + +import com.android.settings.Settings; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + + +@RunWith(AndroidJUnit4.class) +public class SavedNetworkSettingsTest { + + // Keys used to lookup resources by name (see the resourceId helper method). + private static final String STRING = "string"; + private static final String WIFI_ADD_NETWORK = "wifi_add_network"; + private static final String WIFI_NETWORK_LABEL = "wifi_ssid"; + + private Context mContext; + + @Rule + public ActivityTestRule mActivityRule = + new ActivityTestRule<>(Settings.SavedAccessPointsSettingsActivity.class, true); + + private int resourceId(String type, String name) { + return mContext.getResources().getIdentifier(name, type, mContext.getPackageName()); + } + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getTargetContext(); + } + + private void launchSavedNetworksSettings() { + Intent intent = new Intent() + .setClassName(mContext.getPackageName(), + Settings.SavedAccessPointsSettingsActivity.class.getName()) + .setPackage(mContext.getPackageName()); + mActivityRule.launchActivity(intent); + } + + @Test + public void launchSavedNetworkSettings_shouldHaveAddNetworkField() { + launchSavedNetworksSettings(); + onView(withText(resourceId(STRING, WIFI_ADD_NETWORK))).check(matches(isDisplayed())) + .perform(click()); + onView(withText(resourceId(STRING, WIFI_NETWORK_LABEL))).check(matches(isDisplayed())); + } +} From 98fc9b139c4bfd2b6637d02ad5e0bb3de32f7251 Mon Sep 17 00:00:00 2001 From: Soroosh Mariooryad Date: Tue, 8 Aug 2017 11:21:32 -0700 Subject: [PATCH 4/6] Extending SearchFeatureProvider API to provide timeout Bug: 38197948 Test: RunSettingsRoboTests Change-Id: I5b04085ba93061dafe8977b42ebe5092bc9a9d09 --- src/com/android/settings/search/SearchFeatureProvider.java | 7 +++++++ src/com/android/settings/search/SearchResultsAdapter.java | 6 ++---- .../android/settings/search/SearchResultsAdapterTest.java | 2 ++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java index 900cefc3a53..956808d3857 100644 --- a/src/com/android/settings/search/SearchFeatureProvider.java +++ b/src/com/android/settings/search/SearchFeatureProvider.java @@ -137,6 +137,13 @@ public interface SearchFeatureProvider { return false; } + /** + * @return smart ranking timeout in milliseconds. + */ + default long smartSearchRankingTimeoutMs(Context context) { + return 300L; + } + /** * Prepare for search ranking predictions to avoid latency on the first prediction call. */ diff --git a/src/com/android/settings/search/SearchResultsAdapter.java b/src/com/android/settings/search/SearchResultsAdapter.java index 7b886a46cd0..5fedc523583 100644 --- a/src/com/android/settings/search/SearchResultsAdapter.java +++ b/src/com/android/settings/search/SearchResultsAdapter.java @@ -64,9 +64,6 @@ public class SearchResultsAdapter extends RecyclerView.Adapter @VisibleForTesting static final int MSG_RANKING_TIMED_OUT = 1; - // TODO(b/38197948): Tune this timeout based on latency of static and async rankings. Also, we - // should add a gservices flag to control this. - private static final long RANKING_TIMEOUT_MS = 300; private final SearchFragment mFragment; private final Context mContext; private final List mSearchResults; @@ -245,8 +242,9 @@ public class SearchResultsAdapter extends RecyclerView.Adapter mAsyncRankingState = PENDING_RESULTS; mSearchFeatureProvider.cancelPendingSearchQuery(mContext); final Handler handler = getHandler(); + final long timeoutMs = mSearchFeatureProvider.smartSearchRankingTimeoutMs(mContext); handler.sendMessageDelayed( - handler.obtainMessage(MSG_RANKING_TIMED_OUT), RANKING_TIMEOUT_MS); + handler.obtainMessage(MSG_RANKING_TIMED_OUT), timeoutMs); mSearchFeatureProvider.querySearchResults(mContext, query, this); } else { mAsyncRankingState = DISABLED; diff --git a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java b/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java index e605ec1729b..a2afb3570c6 100644 --- a/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java +++ b/tests/robotests/src/com/android/settings/search/SearchResultsAdapterTest.java @@ -83,6 +83,8 @@ public class SearchResultsAdapterTest { mLoaderClassName = DatabaseResultLoader.class.getName(); when(mFragment.getContext()).thenReturn(mMockContext); when(mMockContext.getApplicationContext()).thenReturn(mContext); + when(mSearchFeatureProvider.smartSearchRankingTimeoutMs(any(Context.class))) + .thenReturn(300L); mAdapter = new SearchResultsAdapter(mFragment, mSearchFeatureProvider); } From 72ebf8fe356bfbca3eeaf7c9b3dfa807c5b458bc Mon Sep 17 00:00:00 2001 From: Steven Timotius Date: Tue, 22 Aug 2017 17:47:12 -0700 Subject: [PATCH 5/6] Fix to show correct value for data limit setting Bug: 64901297 Test: Manually set a value for data limit in Settings, verify text is correct Change-Id: Ieec3ce39b55754b54caefd2be923afe9883682b1 --- src/com/android/settings/datausage/BillingCycleSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java index 7fe0922308a..d00749d837e 100644 --- a/src/com/android/settings/datausage/BillingCycleSettings.java +++ b/src/com/android/settings/datausage/BillingCycleSettings.java @@ -119,7 +119,7 @@ public class BillingCycleSettings extends DataUsageBase implements mDataWarning.setEnabled(false); mEnableDataWarning.setChecked(false); } - final long limitBytes = services.mPolicyEditor.getPolicyWarningBytes(mNetworkTemplate); + final long limitBytes = services.mPolicyEditor.getPolicyLimitBytes(mNetworkTemplate); if (limitBytes != LIMIT_DISABLED) { mDataLimit.setSummary(Formatter.formatFileSize(getContext(), limitBytes)); mDataLimit.setEnabled(true); From 4242ee0dd4244fcf90b38a941ae61116d8e88127 Mon Sep 17 00:00:00 2001 From: jackqdyulei Date: Tue, 15 Aug 2017 11:01:07 -0700 Subject: [PATCH 6/6] Set preference invisible when no anomaly In the previous code path, we will create an invisible anomaly preference and update it to visible if it contains any anomaly. However, when anomaly is dismissed we don't reset preference to invisible. So, this cl adds code to set it to invisible explicitly when anomaly list is empty. Bug: 64617126 Test: RunSettingsRoboTests Change-Id: Ie7a3498da91243f05f4c47fb1cc5f67b177d04b1 --- .../anomaly/AnomalySummaryPreferenceController.java | 2 ++ .../AnomalySummaryPreferenceControllerTest.java | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java b/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java index 59c8b2c6838..6bfc9ffb76a 100644 --- a/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java +++ b/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceController.java @@ -102,6 +102,8 @@ public class AnomalySummaryPreferenceController { mAnomalyPreference.setTitle(title); mAnomalyPreference.setSummary(summary); + } else { + mAnomalyPreference.setVisible(false); } } diff --git a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceControllerTest.java index 72d8b691866..8297e810b60 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/anomaly/AnomalySummaryPreferenceControllerTest.java @@ -106,6 +106,16 @@ public class AnomalySummaryPreferenceControllerTest { assertThat(mPreference.getSummary()).isEqualTo("Keeping device awake"); } + @Test + public void testUpdateAnomalySummaryPreference_emptyAnomaly_preferenceInvisible() { + mPreference.setVisible(true); + mAnomalyList.clear(); + + mAnomalySummaryPreferenceController.updateAnomalySummaryPreference(mAnomalyList); + + assertThat(mPreference.isVisible()).isFalse(); + } + @Test public void testUpdateAnomalySummaryPreference_multipleAnomalies_showCorrectSummary() { mAnomalyList.add(createTestAnomaly());