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/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); 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/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/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/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java index 5c8e42be387..0e4c5422ec6 100644 --- a/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java +++ b/src/com/android/settings/wifi/SavedAccessPointsWifiSettings.java @@ -16,6 +16,7 @@ package com.android.settings.wifi; +import android.annotation.Nullable; import android.app.Dialog; import android.content.Context; import android.icu.text.Collator; @@ -40,6 +41,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 { @@ -75,6 +77,7 @@ public class SavedAccessPointsWifiSettings extends SettingsPreferenceFragment private AccessPoint mDlgAccessPoint; private Bundle mAccessPointSavedState; private AccessPoint mSelectedAccessPoint; + private Preference mAddNetworkPreference; private AccessPointPreference.UserBadgeCache mUserBadgeCache; @@ -134,23 +137,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); } @@ -159,15 +177,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); @@ -225,9 +251,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/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 = 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 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()); 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); } 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())); + } +}