Snap for 5112637 from 998eaa0585 to qt-release

Change-Id: I0b6a993115c9d7bd9c34a135a9e2750e94013a29
This commit is contained in:
android-build-team Robot
2018-11-06 04:13:26 +00:00
23 changed files with 488 additions and 177 deletions

View File

@@ -60,4 +60,9 @@
# Keep classes that implements CustomSliceable, which are used by reflection.
-keepclasseswithmembers class * implements com.android.settings.slices.CustomSliceable {
public <init>(android.content.Context);
}
}
# Keep classes that extends SliceBackgroundWorker, which are used by reflection.
-keepclasseswithmembers class * extends com.android.settings.slices.SliceBackgroundWorker {
public <init>(android.content.Context, android.net.Uri);
}

View File

@@ -0,0 +1,27 @@
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ff4285f4"
android:pathData="M12,2C6.48,2 2,6.48 2,12c0,5.52 4.48,10 10,10c5.52,0 10,-4.48 10,-10C22,6.48 17.52,2 12,2zM7.07,18.28c0.43,-0.9 3.05,-1.78 4.93,-1.78s4.51,0.88 4.93,1.78C15.57,19.36 13.86,20 12,20S8.43,19.36 7.07,18.28zM18.36,16.83c-1.43,-1.74 -4.9,-2.33 -6.36,-2.33s-4.93,0.59 -6.36,2.33C4.62,15.49 4,13.82 4,12c0,-4.41 3.59,-8 8,-8c4.41,0 8,3.59 8,8C20,13.82 19.38,15.49 18.36,16.83z"/>
<path
android:fillColor="#ff4285f4"
android:pathData="M12,6c-1.94,0 -3.5,1.56 -3.5,3.5S10.06,13 12,13c1.94,0 3.5,-1.56 3.5,-3.5S13.94,6 12,6zM12,11c-0.83,0 -1.5,-0.67 -1.5,-1.5C10.5,8.67 11.17,8 12,8c0.83,0 1.5,0.67 1.5,1.5C13.5,10.33 12.83,11 12,11z"/>
</vector>

View File

@@ -19,5 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height=".75dp"
android:background="?android:attr/dividerHorizontal" />
android:layout_height="@dimen/horizontal_divider_height"
android:layout_marginTop="@dimen/horizontal_divider_margin_top"
android:layout_marginBottom="@dimen/horizontal_divider_margin_bottom"
android:background="?android:attr/dividerHorizontal"/>

View File

@@ -45,5 +45,12 @@
android:layout_height="wrap_content"
android:text="@string/search_menu"/>
</Toolbar>
<ImageView
android:id="@+id/account_avatar"
android:layout_marginStart="@dimen/search_bar_avatar_start_margin"
android:layout_marginEnd="@dimen/search_bar_avatar_end_margin"
android:layout_width="@dimen/search_bar_avatar_size"
android:layout_height="@dimen/search_bar_avatar_size"
android:layout_gravity="end|center_vertical"/>
</androidx.cardview.widget.CardView>
</FrameLayout>

View File

@@ -27,32 +27,5 @@
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_animation_fall_down"/>
<RelativeLayout
android:id="@+id/suggestion_footer"
android:layout_width="match_parent"
android:layout_height="@dimen/condition_header_height"
android:layout_centerHorizontal="true">
<ImageView
android:id="@+id/expand_indicator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:paddingTop="4dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"/>
<TextView
android:id="@+id/expand_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_toStartOf="@id/expand_indicator"
android:layout_centerVertical="true"
android:gravity="end"
android:textAppearance="@style/TextAppearance.SuggestionTitle"
android:textColor="?android:attr/colorAccent"/>
</RelativeLayout>
<include layout="@layout/horizontal_divider"/>
</LinearLayout>

View File

@@ -103,6 +103,9 @@
<dimen name="search_bar_text_size">16dp</dimen>
<dimen name="search_bar_card_elevation">2dp</dimen>
<dimen name="search_bar_content_inset">64dp</dimen>
<dimen name="search_bar_avatar_size">32dp</dimen>
<dimen name="search_bar_avatar_start_margin">4dp</dimen>
<dimen name="search_bar_avatar_end_margin">16dp</dimen>
<!-- Dimensions for Wifi Assistant Card -->
<dimen name="wifi_assistant_padding_top_bottom">16dp</dimen>
@@ -327,11 +330,16 @@
<!-- Homepage cards size and padding -->
<dimen name="homepage_card_corner_radius">8dp</dimen>
<dimen name="homepage_card_elevation">2dp</dimen>
<dimen name="homepage_card_vertical_margin">6dp</dimen>
<dimen name="homepage_card_side_margin">16dp</dimen>
<dimen name="homepage_card_vertical_margin">4dp</dimen>
<dimen name="homepage_card_side_margin">8dp</dimen>
<dimen name="homepage_card_padding_start">16dp</dimen>
<dimen name="homepage_card_padding_end">16dp</dimen>
<!-- Horizontal divider size and margin -->
<dimen name="horizontal_divider_margin_top">4dp</dimen>
<dimen name="horizontal_divider_margin_bottom">8dp</dimen>
<dimen name="horizontal_divider_height">.75dp</dimen>
<!-- Signal icon in NetworkSelectSetting -->
<dimen name="signal_strength_icon_size">24dp</dimen>

View File

@@ -7278,9 +7278,9 @@
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_peek">Don\'t pop notifications on screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_status">Hide status bar icons</string>
<string name="zen_mode_block_effect_status">Hide status bar icons at top of screen</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_badge">Hide notification dots</string>
<string name="zen_mode_block_effect_badge">Hide notification dots on app icons</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->
<string name="zen_mode_block_effect_ambient">Don\'t wake for notifications</string>
<!-- Do not disturb: what to block option [CHAR LIMIT=NONE] -->

View File

@@ -20,6 +20,9 @@
android:title="@string/wifi_settings"
settings:keywords="@string/keywords_wifi">
<com.android.settings.wifi.LinkablePreference
android:key="wifi_status_message"/>
<PreferenceCategory
android:key="connected_access_point"
android:layout="@layout/preference_category_no_label"/>
@@ -28,17 +31,14 @@
android:key="access_points"
android:layout="@layout/preference_category_no_label"/>
<PreferenceCategory
android:key="additional_settings"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="configure_settings"
android:title="@string/wifi_configure_settings_preference_title"
android:fragment="com.android.settings.wifi.ConfigureWifiSettings" />
<Preference
android:key="configure_settings"
android:title="@string/wifi_configure_settings_preference_title"
settings:allowDividerAbove="true"
android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
<Preference
android:key="saved_networks"
android:title="@string/wifi_saved_access_points_label"
android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings" />
</PreferenceCategory>
<Preference
android:key="saved_networks"
android:title="@string/wifi_saved_access_points_label"
android:fragment="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings"/>
</PreferenceScreen>

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2018 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.accounts;
import android.accounts.Account;
import android.content.Context;
import android.widget.ImageView;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import com.android.settings.R;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.overlay.FeatureFactory;
/**
* Avatar related work to the onStart method of registered observable classes
* in {@link SettingsHomepageActivity}.
*/
public class AvatarViewMixin implements LifecycleObserver {
private Context mContext;
private ImageView mAvatarView;
public AvatarViewMixin(Context context, ImageView avatarView) {
mContext = context.getApplicationContext();
mAvatarView = avatarView;
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
if (hasAccount()) {
//TODO(b/117509285): To migrate account icon on search bar
} else {
mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp);
}
}
@VisibleForTesting
boolean hasAccount() {
final Account accounts[] = FeatureFactory.getFactory(
mContext).getAccountFeatureProvider().getAccounts(mContext);
return (accounts != null) && (accounts.length > 0);
}
}

View File

@@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.VisibleForTesting;
@@ -34,8 +35,7 @@ import java.util.List;
public class TimeSpentInAppPreferenceController extends BasePreferenceController {
@VisibleForTesting
static final Intent SEE_TIME_IN_APP_TEMPLATE =
new Intent("com.android.settings.action.TIME_SPENT_IN_APP");
static final Intent SEE_TIME_IN_APP_TEMPLATE = new Intent(Settings.ACTION_APP_USAGE_SETTINGS);
private final PackageManager mPackageManager;

View File

@@ -19,6 +19,7 @@ package com.android.settings.homepage;
import android.content.Intent;
import android.os.Bundle;
import android.util.FeatureFlagUtils;
import android.widget.ImageView;
import android.widget.Toolbar;
import androidx.fragment.app.Fragment;
@@ -27,6 +28,7 @@ import androidx.fragment.app.FragmentTransaction;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.accounts.AvatarViewMixin;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
@@ -51,6 +53,10 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
FeatureFactory.getFactory(this).getSearchFeatureProvider()
.initSearchToolbar(this, toolbar);
final ImageView avatarView = findViewById(R.id.account_avatar);
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(this, avatarView);
getLifecycle().addObserver(avatarViewMixin);
showFragment(new ContextualCardsFragment(), R.id.contextual_cards_content);
showFragment(new TopLevelSettings(), R.id.main_content);
}

View File

@@ -62,12 +62,13 @@ public class ApnPreferenceController extends BasePreferenceController implements
public int getAvailabilityStatus() {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
final boolean isCdmaApn = MobileNetworkUtils.isCdmaOptions(mContext, mSubId)
&& carrierConfig != null
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_APN_SETTING_CDMA_BOOL);
final boolean isGsmApn = MobileNetworkUtils.isGsmOptions(mContext, mSubId)
&& carrierConfig != null
&& carrierConfig.getBoolean(CarrierConfigManager.KEY_APN_EXPAND_BOOL);
return carrierConfig != null
&& (isCdmaApn || isGsmApn)
return isCdmaApn || isGsmApn
? AVAILABLE
: CONDITIONALLY_UNAVAILABLE;
}

View File

@@ -24,13 +24,10 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.util.Slog;
import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
@@ -38,6 +35,10 @@ import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
@@ -128,9 +129,13 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
@Override
public void onOk(String ruleName, Fragment parent) {
if (TextUtils.equals(ruleName, mRule.getName())) {
return;
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mRule.setModified(true);
mBackend.setZenRule(mId, mRule);
}
}

View File

@@ -91,11 +91,12 @@ public interface CustomSliceable {
/**
* Settings Slices which can represent component lists that are updatable by the
* {@link SliceBackgroundWorker} returned here.
* {@link SliceBackgroundWorker} class returned here.
*
* @return a {@link SliceBackgroundWorker} for fetching the list of results in the background.
* @return a {@link SliceBackgroundWorker} class for fetching the list of results in the
* background.
*/
default SliceBackgroundWorker getBackgroundWorker() {
default Class<? extends SliceBackgroundWorker> getBackgroundWorkerClass() {
return null;
}

View File

@@ -52,7 +52,6 @@ import com.android.settings.wifi.calling.WifiCallingSliceHelper;
import com.android.settingslib.SliceBroadcastRelay;
import com.android.settingslib.utils.ThreadUtils;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -134,8 +133,7 @@ public class SettingsSliceProvider extends SliceProvider {
final Set<Uri> mRegisteredUris = new ArraySet<>();
final Map<Uri, SliceBackgroundWorker> mWorkerMap = new ArrayMap<>();
final Set<SliceBackgroundWorker> mLiveWorkers = new ArraySet<>();
final Map<Uri, SliceBackgroundWorker> mPinnedWorkers = new ArrayMap<>();
public SettingsSliceProvider() {
super(READ_SEARCH_INDEXABLES);
@@ -365,45 +363,37 @@ public class SettingsSliceProvider extends SliceProvider {
}
private void startBackgroundWorker(CustomSliceable sliceable) {
final SliceBackgroundWorker worker = sliceable.getBackgroundWorker();
if (worker == null) {
final Class workerClass = sliceable.getBackgroundWorkerClass();
if (workerClass == null) {
return;
}
final Uri uri = sliceable.getUri();
if (mWorkerMap.containsKey(uri)) {
if (mPinnedWorkers.containsKey(uri)) {
return;
}
Log.d(TAG, "Starting background worker for: " + uri);
mWorkerMap.put(uri, worker);
if (!mLiveWorkers.contains(worker)) {
mLiveWorkers.add(worker);
}
final SliceBackgroundWorker worker = SliceBackgroundWorker.getInstance(
getContext(), sliceable);
mPinnedWorkers.put(uri, worker);
worker.onSlicePinned();
}
private void stopBackgroundWorker(Uri uri) {
final SliceBackgroundWorker worker = mWorkerMap.get(uri);
final SliceBackgroundWorker worker = mPinnedWorkers.get(uri);
if (worker != null) {
Log.d(TAG, "Stopping background worker for: " + uri);
worker.onSliceUnpinned();
mWorkerMap.remove(uri);
mPinnedWorkers.remove(uri);
}
}
@Override
public void shutdown() {
for (SliceBackgroundWorker worker : mLiveWorkers) {
ThreadUtils.postOnMainThread(() -> {
try {
worker.close();
} catch (IOException e) {
Log.w(TAG, "Exception when shutting down worker", e);
}
});
}
mLiveWorkers.clear();
ThreadUtils.postOnMainThread(() -> {
SliceBackgroundWorker.shutdown();
});
}
private List<Uri> buildUrisFromKeys(List<String> keys, String authority) {
@@ -532,4 +522,4 @@ public class SettingsSliceProvider extends SliceProvider {
}
return new String[0];
}
}
}

View File

@@ -17,35 +17,86 @@
package com.android.settings.slices;
import android.annotation.MainThread;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.util.ArrayMap;
import android.util.Log;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* The Slice background worker is used to make Settings Slices be able to work with data that is
* changing continuously, e.g. available Wi-Fi networks.
*
* The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, and be
* stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}.
* The background worker will be started at {@link SettingsSliceProvider#onSlicePinned(Uri)}, be
* stopped at {@link SettingsSliceProvider#onSliceUnpinned(Uri)}, and be closed at {@link
* SettingsSliceProvider#shutdown()}.
*
* {@link SliceBackgroundWorker} caches the results, uses the cache to compare if there is any data
* changed, and then notifies the Slice {@link Uri} to update.
*
* It also stores all instances of all workers to ensure each worker is a Singleton.
*/
public abstract class SliceBackgroundWorker<E> implements Closeable {
private final ContentResolver mContentResolver;
private static final String TAG = "SliceBackgroundWorker";
private static final Map<Uri, SliceBackgroundWorker> LIVE_WORKERS = new ArrayMap<>();
private final Context mContext;
private final Uri mUri;
private List<E> mCachedResults;
protected SliceBackgroundWorker(ContentResolver cr, Uri uri) {
mContentResolver = cr;
protected SliceBackgroundWorker(Context context, Uri uri) {
mContext = context;
mUri = uri;
}
/**
* Returns the singleton instance of the {@link SliceBackgroundWorker} for specified {@link
* CustomSliceable}
*/
public static SliceBackgroundWorker getInstance(Context context, CustomSliceable sliceable) {
final Uri uri = sliceable.getUri();
final Class<? extends SliceBackgroundWorker> workerClass =
sliceable.getBackgroundWorkerClass();
SliceBackgroundWorker worker = LIVE_WORKERS.get(uri);
if (worker == null) {
worker = createInstance(context, uri, workerClass);
LIVE_WORKERS.put(uri, worker);
}
return worker;
}
private static SliceBackgroundWorker createInstance(Context context, Uri uri,
Class<? extends SliceBackgroundWorker> clazz) {
Log.d(TAG, "create instance: " + clazz);
try {
return clazz.getConstructor(Context.class, Uri.class).newInstance(context, uri);
} catch (NoSuchMethodException | IllegalAccessException | InstantiationException |
InvocationTargetException e) {
throw new IllegalStateException(
"Invalid slice background worker: " + clazz, e);
}
}
static void shutdown() {
for (SliceBackgroundWorker worker : LIVE_WORKERS.values()) {
try {
worker.close();
} catch (IOException e) {
Log.w(TAG, "Shutting down worker failed", e);
}
}
LIVE_WORKERS.clear();
}
/**
* Called when the Slice is pinned. This is the place to register callbacks or initialize scan
* tasks.
@@ -83,7 +134,7 @@ public abstract class SliceBackgroundWorker<E> implements Closeable {
if (needNotify) {
mCachedResults = results;
mContentResolver.notifyChange(mUri, null);
mContext.getContentResolver().notifyChange(mUri, null);
}
}
}

View File

@@ -251,15 +251,20 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
updateWidgetState(false);
}
@Override
public void onDone(String utteranceId) {
updateWidgetState(true);
}
@Override
public void onError(String utteranceId) {
Log.e(TAG, "Error while trying to synthesize sample text");
// Re-enable just in case, although there isn't much hope that following synthesis
// requests are going to succeed.
updateWidgetState(true);
}
});
}
@@ -696,9 +701,11 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
}
private void updateWidgetState(boolean enable) {
mActionButtons.setButton1Enabled(enable);
mDefaultRatePref.setEnabled(enable);
mDefaultPitchPref.setEnabled(enable);
getActivity().runOnUiThread(() -> {
mActionButtons.setButton1Enabled(enable);
mDefaultRatePref.setEnabled(enable);
mDefaultPitchPref.setEnabled(enable);
});
}
private void displayNetworkAlert() {

View File

@@ -112,9 +112,9 @@ public class WifiSettings extends RestrictedSettingsFragment
private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list";
private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point";
private static final String PREF_KEY_ACCESS_POINTS = "access_points";
private static final String PREF_KEY_ADDITIONAL_SETTINGS = "additional_settings";
private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings";
private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
private static boolean isVerboseLoggingEnabled() {
return WifiTracker.sVerboseLogging || Log.isLoggable(TAG, Log.VERBOSE);
@@ -167,17 +167,19 @@ public class WifiSettings extends RestrictedSettingsFragment
private Bundle mAccessPointSavedState;
private Bundle mWifiNfcDialogSavedState;
private WifiTracker mWifiTracker;
@VisibleForTesting
WifiTracker mWifiTracker;
private String mOpenSsid;
private AccessPointPreference.UserBadgeCache mUserBadgeCache;
private PreferenceCategory mConnectedAccessPointPreferenceCategory;
private PreferenceCategory mAccessPointsPreferenceCategory;
private PreferenceCategory mAdditionalSettingsPreferenceCategory;
private Preference mAddPreference;
private Preference mConfigureWifiSettingsPreference;
private Preference mSavedNetworksPreference;
@VisibleForTesting
Preference mConfigureWifiSettingsPreference;
@VisibleForTesting
Preference mSavedNetworksPreference;
private LinkablePreference mStatusMessagePreference;
// For Search
@@ -229,8 +231,6 @@ public class WifiSettings extends RestrictedSettingsFragment
(PreferenceCategory) findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);
mAccessPointsPreferenceCategory =
(PreferenceCategory) findPreference(PREF_KEY_ACCESS_POINTS);
mAdditionalSettingsPreferenceCategory =
(PreferenceCategory) findPreference(PREF_KEY_ADDITIONAL_SETTINGS);
mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);
mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);
@@ -238,7 +238,7 @@ public class WifiSettings extends RestrictedSettingsFragment
mAddPreference = new Preference(prefContext);
mAddPreference.setIcon(R.drawable.ic_menu_add);
mAddPreference.setTitle(R.string.wifi_add_network);
mStatusMessagePreference = new LinkablePreference(prefContext);
mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);
mUserBadgeCache = new AccessPointPreference.UserBadgeCache(getPackageManager());
}
@@ -692,14 +692,14 @@ public class WifiSettings extends RestrictedSettingsFragment
case WifiManager.WIFI_STATE_ENABLING:
removeConnectedAccessPointPreference();
mAccessPointsPreferenceCategory.removeAll();
removeAccessPointPreference();
addMessagePreference(R.string.wifi_starting);
setProgressBarVisible(true);
break;
case WifiManager.WIFI_STATE_DISABLING:
removeConnectedAccessPointPreference();
mAccessPointsPreferenceCategory.removeAll();
removeAccessPointPreference();
addMessagePreference(R.string.wifi_stopping);
break;
@@ -746,7 +746,10 @@ public class WifiSettings extends RestrictedSettingsFragment
}
boolean hasAvailableAccessPoints = false;
mAccessPointsPreferenceCategory.removePreference(mStatusMessagePreference);
mStatusMessagePreference.setVisible(false);
mConnectedAccessPointPreferenceCategory.setVisible(true);
mAccessPointsPreferenceCategory.setVisible(true);
cacheRemoveAllPrefs(mAccessPointsPreferenceCategory);
int index =
@@ -960,26 +963,28 @@ public class WifiSettings extends RestrictedSettingsFragment
unregisterCaptivePortalNetworkCallback();
}
private void setAdditionalSettingsSummaries() {
mAdditionalSettingsPreferenceCategory.addPreference(mConfigureWifiSettingsPreference);
private void removeAccessPointPreference() {
mAccessPointsPreferenceCategory.removeAll();
mAccessPointsPreferenceCategory.setVisible(false);
}
@VisibleForTesting
void setAdditionalSettingsSummaries() {
mConfigureWifiSettingsPreference.setSummary(getString(
isWifiWakeupEnabled()
? R.string.wifi_configure_settings_preference_summary_wakeup_on
: R.string.wifi_configure_settings_preference_summary_wakeup_off));
int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
if (numSavedNetworks > 0) {
mAdditionalSettingsPreferenceCategory.addPreference(mSavedNetworksPreference);
mSavedNetworksPreference.setSummary(
getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
numSavedNetworks, numSavedNetworks));
} else {
mAdditionalSettingsPreferenceCategory.removePreference(mSavedNetworksPreference);
}
final int numSavedNetworks = mWifiTracker.getNumSavedNetworks();
mSavedNetworksPreference.setVisible(numSavedNetworks > 0);
mSavedNetworksPreference.setSummary(
getResources().getQuantityString(R.plurals.wifi_saved_access_points_summary,
numSavedNetworks, numSavedNetworks));
}
private boolean isWifiWakeupEnabled() {
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
ContentResolver contentResolver = getContentResolver();
final Context context = getContext();
final PowerManager powerManager = context.getSystemService(PowerManager.class);
final ContentResolver contentResolver = context.getContentResolver();
return Settings.Global.getInt(contentResolver,
Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1
&& Settings.Global.getInt(contentResolver,
@@ -1006,15 +1011,14 @@ public class WifiSettings extends RestrictedSettingsFragment
.launch();
mStatusMessagePreference.setText(title, description, clickListener);
removeConnectedAccessPointPreference();
mAccessPointsPreferenceCategory.removeAll();
mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
removeAccessPointPreference();
mStatusMessagePreference.setVisible(true);
}
private void addMessagePreference(int messageId) {
mStatusMessagePreference.setTitle(messageId);
removeConnectedAccessPointPreference();
mAccessPointsPreferenceCategory.removeAll();
mAccessPointsPreferenceCategory.addPreference(mStatusMessagePreference);
mStatusMessagePreference.setVisible(true);
}
protected void setProgressBarVisible(boolean visible) {

View File

@@ -121,7 +121,7 @@ public class WifiSlice implements CustomSliceable {
return listBuilder.build();
}
List<AccessPoint> results = getBackgroundWorker().getResults();
List<AccessPoint> results = SliceBackgroundWorker.getInstance(mContext, this).getResults();
if (results == null) {
results = new ArrayList<>();
}
@@ -264,36 +264,27 @@ public class WifiSlice implements CustomSliceable {
}
@Override
public SliceBackgroundWorker getBackgroundWorker() {
return WifiScanWorker.getInstance(mContext, WIFI_URI);
public Class getBackgroundWorkerClass() {
return WifiScanWorker.class;
}
private static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
public static class WifiScanWorker extends SliceBackgroundWorker<AccessPoint>
implements WifiTracker.WifiListener {
// TODO: enforce all the SliceBackgroundWorkers being singletons at syntax level
private static WifiScanWorker mWifiScanWorker;
private final Context mContext;
private WifiTracker mWifiTracker;
private WifiScanWorker(Context context, Uri uri) {
super(context.getContentResolver(), uri);
public WifiScanWorker(Context context, Uri uri) {
super(context, uri);
mContext = context;
}
public static WifiScanWorker getInstance(Context context, Uri uri) {
if (mWifiScanWorker == null) {
mWifiScanWorker = new WifiScanWorker(context, uri);
}
return mWifiScanWorker;
}
@Override
protected void onSlicePinned() {
if (mWifiTracker == null) {
mWifiTracker = new WifiTracker(mContext, this, true, true);
mWifiTracker = new WifiTracker(mContext, this /* wifiListener */,
true /* includeSaved */, true /* includeScans */);
}
mWifiTracker.onStart();
onAccessPointsChanged();
@@ -307,7 +298,6 @@ public class WifiSlice implements CustomSliceable {
@Override
public void close() {
mWifiTracker.onDestroy();
mWifiScanWorker = null;
}
@Override

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2018 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.accounts;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.accounts.Account;
import android.content.Context;
import android.widget.ImageView;
import com.android.settings.homepage.SettingsHomepageActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@RunWith(SettingsRobolectricTestRunner.class)
public class AvatarViewMixinTest {
private static final String DUMMY_ACCOUNT = "test@domain.com";
private static final String DUMMY_DOMAIN = "domain.com";
private Context mContext;
private ImageView mImageView;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mImageView = new ImageView(mContext);
}
@Test
public void hasAccount_useDefaultAccountData_returnFalse() {
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
assertThat(avatarViewMixin.hasAccount()).isFalse();
}
@Test
@Config(shadows = ShadowAccountFeatureProviderImpl.class)
public void hasAccount_useShadowAccountData_returnTrue() {
final AvatarViewMixin avatarViewMixin = new AvatarViewMixin(mContext, mImageView);
assertThat(avatarViewMixin.hasAccount()).isTrue();
}
@Test
public void onStart_useMockAvatarViewMixin_shouldBeExecuted() {
final AvatarViewMixin mockAvatar = spy(new AvatarViewMixin(mContext, mImageView));
final ActivityController controller = Robolectric.buildActivity(
SettingsHomepageActivity.class).create();
final SettingsHomepageActivity settingsHomepageActivity =
(SettingsHomepageActivity) controller.get();
settingsHomepageActivity.getLifecycle().addObserver(mockAvatar);
controller.start();
verify(mockAvatar).onStart();
}
@Implements(AccountFeatureProviderImpl.class)
public static class ShadowAccountFeatureProviderImpl {
@Implementation
public Account[] getAccounts(Context context) {
Account[] accounts = {new Account(DUMMY_ACCOUNT, DUMMY_DOMAIN)};
return accounts;
}
}
}

View File

@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
@@ -114,6 +115,14 @@ public class ApnPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_carrierConfigNull_returnUnavailable() {
doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mTelephonyManager).getPhoneType();
when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(null);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void handPreferenceTreeClick_fireIntent() {
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);

View File

@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -60,6 +61,7 @@ import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settings.wifi.WifiSlice;
import com.android.settingslib.wifi.WifiTracker;
import org.junit.After;
import org.junit.Before;
@@ -75,7 +77,6 @@ import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowAccessibilityManager;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -91,7 +92,8 @@ import java.util.Set;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class, ShadowThreadUtils.class, ShadowUtils.class,
SlicesDatabaseAccessorTest.ShadowApplicationPackageManager.class,
ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class})
ShadowBluetoothAdapter.class, ShadowLockPatternUtils.class,
SettingsSliceProviderTest.ShadowWifiScanWorker.class})
public class SettingsSliceProviderTest {
private static final String KEY = "KEY";
@@ -135,7 +137,7 @@ public class SettingsSliceProviderTest {
mProvider.mSliceWeakDataCache = new HashMap<>();
mProvider.mSliceDataCache = new HashMap<>();
mProvider.mSlicesDatabaseAccessor = new SlicesDatabaseAccessor(mContext);
mProvider.mCustomSliceManager = spy(new CustomSliceManager(mContext));
mProvider.mCustomSliceManager = new CustomSliceManager(mContext);
when(mProvider.getContext()).thenReturn(mContext);
SlicesDatabaseHelper.getInstance(mContext).setIndexedState();
@@ -497,57 +499,52 @@ public class SettingsSliceProviderTest {
mProvider.onSlicePinned(uri);
}
private SliceBackgroundWorker initBackgroundWorker(Uri uri) {
final SliceBackgroundWorker worker = spy(new SliceBackgroundWorker(
mContext.getContentResolver(), uri) {
@Override
protected void onSlicePinned() {
}
@Implements(WifiSlice.WifiScanWorker.class)
public static class ShadowWifiScanWorker {
private static WifiTracker mWifiTracker;
@Override
protected void onSliceUnpinned() {
}
@Implementation
protected void onSlicePinned() {
mWifiTracker = mock(WifiTracker.class);
mWifiTracker.onStart();
}
@Override
public void close() {
}
});
final WifiSlice wifiSlice = spy(new WifiSlice(mContext));
when(wifiSlice.getBackgroundWorker()).thenReturn(worker);
when(mProvider.mCustomSliceManager.getSliceableFromUri(uri)).thenReturn(wifiSlice);
return worker;
@Implementation
protected void onSliceUnpinned() {
mWifiTracker.onStop();
}
@Implementation
public void close() {
mWifiTracker.onDestroy();
}
static WifiTracker getWifiTracker() {
return mWifiTracker;
}
}
@Test
public void onSlicePinned_backgroundWorker_started() {
final Uri uri = WifiSlice.WIFI_URI;
final SliceBackgroundWorker worker = initBackgroundWorker(uri);
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.onSlicePinned(uri);
verify(worker).onSlicePinned();
verify(ShadowWifiScanWorker.getWifiTracker()).onStart();
}
@Test
public void onSlicePinned_backgroundWorker_stopped() {
final Uri uri = WifiSlice.WIFI_URI;
final SliceBackgroundWorker worker = initBackgroundWorker(uri);
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.onSliceUnpinned(WifiSlice.WIFI_URI);
mProvider.onSlicePinned(uri);
mProvider.onSliceUnpinned(uri);
verify(worker).onSliceUnpinned();
verify(ShadowWifiScanWorker.getWifiTracker()).onStop();
}
@Test
public void shutdown_backgroundWorker_closed() throws IOException {
final Uri uri = WifiSlice.WIFI_URI;
final SliceBackgroundWorker worker = initBackgroundWorker(uri);
mProvider.onSlicePinned(uri);
public void shutdown_backgroundWorker_closed() {
mProvider.onSlicePinned(WifiSlice.WIFI_URI);
mProvider.shutdown();
verify(worker).close();
verify(ShadowWifiScanWorker.getWifiTracker()).onDestroy();
}
@Test
@@ -630,4 +627,4 @@ public class SettingsSliceProviderTest {
return sSetThreadPolicyCount != 0;
}
}
}
}

View File

@@ -20,20 +20,31 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.wifi.WifiTracker;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -42,18 +53,33 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class WifiSettingsTest {
private static final int NUM_NETWORKS = 4;
@Mock
private WifiTracker mWifiTracker;
@Mock
private PowerManager mPowerManager;
private Context mContext;
private WifiSettings mWifiSettings;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mWifiSettings = spy(new WifiSettings());
doReturn(mContext).when(mWifiSettings).getContext();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
mWifiSettings.mSavedNetworksPreference = new Preference(mContext);
mWifiSettings.mConfigureWifiSettingsPreference = new Preference(mContext);
mWifiSettings.mWifiTracker = mWifiTracker;
}
@Test
public void testSearchIndexProvider_shouldIndexFragmentTitle() {
final List<SearchIndexableRaw> indexRes =
WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
true /* enabled */);
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).key).isEqualTo(WifiSettings.DATA_KEY_REFERENCE);
@@ -63,7 +89,8 @@ public class WifiSettingsTest {
@Config(qualifiers = "mcc999")
public void testSearchIndexProvider_ifWifiSettingsNotVisible_shouldNotIndexFragmentTitle() {
final List<SearchIndexableRaw> indexRes =
WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true /* enabled */);
WifiSettings.SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext,
true /* enabled */);
assertThat(indexRes).isEmpty();
}
@@ -78,4 +105,51 @@ public class WifiSettingsTest {
verify(wifiSettings).handleAddNetworkRequest(anyInt(), any(Intent.class));
}
@Test
public void setAdditionalSettingsSummaries_hasSavedNetwork_preferenceVisible() {
when(mWifiTracker.getNumSavedNetworks()).thenReturn(NUM_NETWORKS);
mWifiSettings.setAdditionalSettingsSummaries();
assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isTrue();
assertThat(mWifiSettings.mSavedNetworksPreference.getSummary()).isEqualTo(
mContext.getResources().getQuantityString(
R.plurals.wifi_saved_access_points_summary,
NUM_NETWORKS, NUM_NETWORKS));
}
@Test
public void setAdditionalSettingsSummaries_noSavedNetwork_preferenceInvisible() {
when(mWifiTracker.getNumSavedNetworks()).thenReturn(0);
mWifiSettings.setAdditionalSettingsSummaries();
assertThat(mWifiSettings.mSavedNetworksPreference.isVisible()).isFalse();
}
@Test
public void setAdditionalSettingsSummaries_wifiWakeupEnabled_displayOn() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 1);
Settings.Global.putInt(contentResolver, Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 1);
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
when(mPowerManager.isPowerSaveMode()).thenReturn(false);
mWifiSettings.setAdditionalSettingsSummaries();
assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_on));
}
@Test
public void setAdditionalSettingsSummaries_wifiWakeupDisabled_displayOff() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.WIFI_WAKEUP_ENABLED, 0);
mWifiSettings.setAdditionalSettingsSummaries();
assertThat(mWifiSettings.mConfigureWifiSettingsPreference.getSummary()).isEqualTo(
mContext.getString(R.string.wifi_configure_settings_preference_summary_wakeup_off));
}
}