Snap for 5187456 from 4eddb1b1a4 to qt-release

Change-Id: Ic752f3bcc64ac1038b87f11f9ac71b14bbb54aaa
This commit is contained in:
android-build-team Robot
2018-12-18 04:04:35 +00:00
167 changed files with 1995 additions and 1358 deletions

View File

@@ -15,6 +15,7 @@ LOCAL_PACKAGE_NAME := Settings
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.settings
LOCAL_MODULE_TAGS := optional
LOCAL_USE_AAPT2 := true
@@ -70,4 +71,4 @@ include $(BUILD_MULTI_PREBUILT)
# Use the following include to make our test apk.
ifeq (,$(ONE_SHOT_MAKEFILE))
include $(call all-makefiles-under,$(LOCAL_PATH))
endif
endif

View File

@@ -1,29 +0,0 @@
<!--
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="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="#FF000000"
android:pathData="M15,14l-2,0l0,2l-2,0l0,-2l-2,0l0,-2l2,0l0,-2l2,0l0,2l2,0z"/>
<path
android:fillColor="#FF000000"
android:pathData="M16.2,22.5H7.8c-1.3,0 -2.3,-1 -2.3,-2.3V5.8c0,-1.3 1,-2.3 2.3,-2.3h0.7v-2h7v2h0.7c1.3,0 2.3,1.1 2.3,2.3v14.3C18.5,21.5 17.5,22.5 16.2,22.5zM7.8,5.5c-0.2,0 -0.3,0.2 -0.3,0.3v14.3c0,0.2 0.2,0.3 0.3,0.3h8.3c0.2,0 0.3,-0.1 0.3,-0.3V5.8c0,-0.2 -0.1,-0.3 -0.3,-0.3h-2.7v-2h-3v2H7.8z"/>
</vector>

View File

@@ -24,20 +24,19 @@
<include layout="@layout/wifi_dpp_fragment_header"/>
<FrameLayout
<com.android.settings.wifi.qrcode.QrPreviewLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:layout_height="match_parent"
android:layout_gravity="center">
<TextureView
android:id="@+id/preview_view"
android:layout_width="426dp"
android:layout_height="320dp"
android:layout_gravity="center"/>
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="426dp"
android:layout_height="320dp"
android:layout_gravity="center"/>
</FrameLayout>
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</com.android.settings.wifi.qrcode.QrPreviewLayout>
<TextView android:id="@+id/error_message"
android:layout_width="wrap_content"

View File

@@ -43,5 +43,6 @@
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"/>
android:layout_gravity="end|center_vertical"
android:contentDescription="@string/search_bar_account_avatar_content_description"/>
</com.google.android.material.card.MaterialCardView>

View File

@@ -24,20 +24,20 @@
<include layout="@layout/wifi_dpp_fragment_header"/>
<FrameLayout
<com.android.settings.wifi.qrcode.QrPreviewLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:layout_height="match_parent">
<TextureView
android:id="@+id/preview_view"
android:layout_width="320dp"
android:layout_height="426dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="320dp"
android:layout_height="426dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"/>
</FrameLayout>
</com.android.settings.wifi.qrcode.QrPreviewLayout>
<TextView android:id="@+id/error_message"
android:layout_width="wrap_content"

View File

@@ -168,6 +168,15 @@
<!-- Whether device_model should be shown or not. -->
<bool name="config_show_device_model">true</bool>
<!-- Whether top_level_battery should be shown or not. -->
<bool name="config_show_top_level_battery">true</bool>
<!-- Whether top_level_connected_devices should be shown or not. -->
<bool name="config_show_top_level_connected_devices">true</bool>
<!-- Whether top_level_display should be shown or not. -->
<bool name="config_show_top_level_display">true</bool>
<!-- Whether wifi_ip_address should be shown or not. -->
<bool name="config_show_wifi_ip_address">true</bool>

View File

@@ -2071,6 +2071,8 @@
<string name="wifi_dpp_scan_qr_code">Scan QR code</string>
<!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_scan_qr_code_join_network">Join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d by scanning a QR code</string>
<!-- Hint for the user to center another device's QR code in the below camera window [CHAR LIMIT=NONE] -->
<string name="wifi_dpp_scan_qr_code_join_unknown_network">Join Wi\u2011Fi by scanning a QR code</string>
<!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50] -->
<string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
<!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
@@ -9019,12 +9021,6 @@
<!-- Summary of condition that do not disturb is on [CHAR LIMIT=36] -->
<string name="condition_zen_summary">Impacts what you hear and see</string>
<!-- Title of condition that battery saver is on [CHAR LIMIT=30] -->
<string name="condition_battery_title">Battery Saver is on</string>
<!-- Summary of condition that battery saver is on [CHAR LIMIT=NONE] -->
<string name="condition_battery_summary">Features restricted</string>
<!-- Title of condition that cellular data is off [CHAR LIMIT=50] -->
<string name="condition_cellular_title">Mobile data is off</string>
@@ -10346,4 +10342,8 @@
<!-- Toast message for copy action of Copyable Slice [CHAR LIMIT=NONE] -->
<string name="copyable_slice_toast"><xliff:g id="copy_content" example="Phone number">%1$s</xliff:g> copied to clipboard.</string>
<!-- String for talkback on the account avatar of the search bar. [CHAR LIMIT=NONE] -->
<string name="search_bar_account_avatar_content_description"></string>
</resources>

View File

@@ -26,18 +26,6 @@
android:title="@string/battery_saver_schedule_settings_title"
settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverSchedulePreferenceController"/>
<!-- Turn on automatically -->
<SwitchPreference
android:key="auto_battery_saver"
android:title="@string/battery_saver_auto_title"
settings:controller="com.android.settings.fuelgauge.batterysaver.AutoBatterySaverPreferenceController" />
<com.android.settings.widget.SeekBarPreference
android:key="battery_saver_seek_bar"
android:title="@string/battery_saver_seekbar_title_placeholder"
android:max="15"
android:min="1" />
<com.android.settings.widget.TwoStateButtonPreference
android:key="battery_saver"
android:title="@string/battery_saver"

View File

@@ -18,8 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="network_and_internet_screen"
android:title="@string/network_dashboard_title"
settings:initialExpandedChildrenCount="5">
android:title="@string/network_dashboard_title">
<PreferenceCategory
android:key="multi_network_header"

View File

@@ -20,7 +20,6 @@ import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;

View File

@@ -29,6 +29,7 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.overlay.FeatureFactory;
/**
* A drawable containing the circle cutout as well as the animations.
@@ -41,17 +42,17 @@ public class FaceEnrollAnimationDrawable extends Drawable
private static final int BORDER_BOUNDS = 20;
private final Context mContext;
private final ParticleCollection.Listener mListener;
private final FaceFeatureProvider.Listener mListener;
private Rect mBounds;
private final Paint mSquarePaint;
private final Paint mCircleCutoutPaint;
private ParticleCollection mParticleCollection;
private FaceFeatureProvider.EnrollingAnimation mEnrollingAnimation;
private TimeAnimator mTimeAnimator;
private final ParticleCollection.Listener mAnimationListener
= new ParticleCollection.Listener() {
private final FaceFeatureProvider.Listener mAnimationListener
= new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
@@ -61,7 +62,7 @@ public class FaceEnrollAnimationDrawable extends Drawable
}
};
public FaceEnrollAnimationDrawable(Context context, ParticleCollection.Listener listener) {
public FaceEnrollAnimationDrawable(Context context, FaceFeatureProvider.Listener listener) {
mContext = context;
mListener = listener;
@@ -77,29 +78,29 @@ public class FaceEnrollAnimationDrawable extends Drawable
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
mParticleCollection.onEnrollmentHelp(helpMsgId, helpString);
mEnrollingAnimation.onEnrollmentHelp(helpMsgId, helpString);
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
mParticleCollection.onEnrollmentError(errMsgId, errString);
mEnrollingAnimation.onEnrollmentError(errMsgId, errString);
}
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
mParticleCollection.onEnrollmentProgressChange(steps, remaining);
mEnrollingAnimation.onEnrollmentProgressChange(steps, remaining);
}
@Override
protected void onBoundsChange(Rect bounds) {
mBounds = bounds;
mParticleCollection =
new ParticleCollection(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
mEnrollingAnimation = FeatureFactory.getFactory(mContext).getFaceFeatureProvider()
.getEnrollingAnimation(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
if (mTimeAnimator == null) {
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener((animation, totalTimeMs, deltaTimeMs) -> {
mParticleCollection.update(totalTimeMs, deltaTimeMs);
mEnrollingAnimation.update(totalTimeMs, deltaTimeMs);
FaceEnrollAnimationDrawable.this.invalidateSelf();
});
mTimeAnimator.start();
@@ -121,7 +122,7 @@ public class FaceEnrollAnimationDrawable extends Drawable
mBounds.height() / 2 - BORDER_BOUNDS, mCircleCutoutPaint);
// Draw the animation
mParticleCollection.draw(canvas);
mEnrollingAnimation.draw(canvas);
canvas.restore();
}

View File

@@ -47,7 +47,7 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
private boolean mShouldFinishOnStop = true;
private FaceEnrollPreviewFragment mPreviewFragment;
private ParticleCollection.Listener mListener = new ParticleCollection.Listener() {
private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
FaceEnrollEnrolling.this.launchFinish(mToken);

View File

@@ -63,7 +63,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
private CameraCaptureSession mCaptureSession;
private CaptureRequest mPreviewRequest;
private Size mPreviewSize;
private ParticleCollection.Listener mListener;
private FaceFeatureProvider.Listener mListener;
// View used to contain the circular cutout and enrollment animation drawable
private ImageView mCircleView;
@@ -75,8 +75,8 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
private FaceSquareTextureView mTextureView;
// Listener sent to the animation drawable
private final ParticleCollection.Listener mAnimationListener
= new ParticleCollection.Listener() {
private final FaceFeatureProvider.Listener mAnimationListener
= new FaceFeatureProvider.Listener() {
@Override
public void onEnrolled() {
mListener.onEnrolled();
@@ -234,7 +234,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
mAnimationDrawable.onEnrollmentProgressChange(steps, remaining);
}
public void setListener(ParticleCollection.Listener listener) {
public void setListener(FaceFeatureProvider.Listener listener) {
mListener = listener;
}

View File

@@ -0,0 +1,42 @@
/*
* 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.biometrics.face;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
/**
* Feature provider for face authentication.
*/
public interface FaceFeatureProvider {
interface EnrollingAnimation {
void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
void onEnrollmentError(int errMsgId, CharSequence errString);
void onEnrollmentProgressChange(int steps, int remaining);
void draw(Canvas canvas);
void update(long t, long dt);
}
interface Listener {
void onEnrolled();
}
EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
int borderWidth);
}

View File

@@ -0,0 +1,28 @@
/*
* 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.biometrics.face;
import android.content.Context;
import android.graphics.Rect;
public class FaceFeatureProviderImpl implements FaceFeatureProvider {
@Override
public EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
int borderWidth) {
return new ParticleCollection(context, listener, bounds, borderWidth);
}
}

View File

@@ -35,7 +35,7 @@ import java.util.List;
* are updated/drawn in a special order so that the overlap is correct during the final completion
* effect.
*/
public class ParticleCollection implements BiometricEnrollSidecar.Listener {
public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnimation {
private static final String TAG = "AnimationController";
@@ -49,11 +49,7 @@ public class ParticleCollection implements BiometricEnrollSidecar.Listener {
private final List<AnimationParticle> mParticleList;
private final List<Integer> mPrimariesInProgress; // primary particles not done animating yet
private int mState;
private Listener mListener;
public interface Listener {
void onEnrolled();
}
private FaceFeatureProvider.Listener mListener;
private final AnimationParticle.Listener mParticleListener = new AnimationParticle.Listener() {
@Override
@@ -72,7 +68,8 @@ public class ParticleCollection implements BiometricEnrollSidecar.Listener {
}
};
public ParticleCollection(Context context, Listener listener, Rect bounds, int borderWidth) {
public ParticleCollection(Context context, FaceFeatureProvider.Listener listener, Rect bounds,
int borderWidth) {
mParticleList = new ArrayList<>();
mListener = listener;
@@ -103,12 +100,14 @@ public class ParticleCollection implements BiometricEnrollSidecar.Listener {
updateState(STATE_STARTED);
}
@Override
public void update(long t, long dt) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).update(t, dt);
}
}
@Override
public void draw(Canvas canvas) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).draw(canvas);

View File

@@ -19,6 +19,7 @@ package com.android.settings.connecteddevice;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.R;
public class TopLevelConnectedDevicesPreferenceController extends BasePreferenceController {
@@ -29,7 +30,9 @@ public class TopLevelConnectedDevicesPreferenceController extends BasePreference
@Override
public int getAvailabilityStatus() {
return AVAILABLE_UNSEARCHABLE;
return mContext.getResources().getBoolean(R.bool.config_show_top_level_connected_devices)
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override

View File

@@ -29,7 +29,9 @@ public class TopLevelDisplayPreferenceController extends BasePreferenceControlle
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
return mContext.getResources().getBoolean(R.bool.config_show_top_level_display)
? AVAILABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.fuelgauge;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
@@ -22,6 +23,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -31,6 +33,7 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
public class BatterySaverController extends BasePreferenceController
implements LifecycleObserver, OnStart, OnStop, BatterySaverReceiver.BatterySaverListener {
@@ -45,6 +48,7 @@ public class BatterySaverController extends BasePreferenceController
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBatteryStateChangeReceiver = new BatterySaverReceiver(context);
mBatteryStateChangeReceiver.setBatterySaverListener(this);
BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
}
@Override
@@ -81,16 +85,23 @@ public class BatterySaverController extends BasePreferenceController
@Override
public CharSequence getSummary() {
final ContentResolver resolver = mContext.getContentResolver();
final boolean isPowerSaveOn = mPowerManager.isPowerSaveMode();
final int percent = Settings.Global.getInt(mContext.getContentResolver(),
final int percent = Settings.Global.getInt(resolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
final int mode = Settings.Global.getInt(resolver,
Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
if (isPowerSaveOn) {
return mContext.getString(R.string.battery_saver_on_summary);
} else if (percent != 0) {
return mContext.getString(R.string.battery_saver_off_scheduled_summary,
Utils.formatPercentage(percent));
} else if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
if (percent != 0) {
return mContext.getString(R.string.battery_saver_off_scheduled_summary,
Utils.formatPercentage(percent));
} else {
return mContext.getString(R.string.battery_saver_off_summary);
}
} else {
return mContext.getString(R.string.battery_saver_off_summary);
return mContext.getString(R.string.battery_saver_auto_routine);
}
}

View File

@@ -48,7 +48,9 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle
@Override
public int getAvailabilityStatus() {
return AVAILABLE_UNSEARCHABLE;
return mContext.getResources().getBoolean(R.bool.config_show_top_level_battery)
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override

View File

@@ -1,70 +0,0 @@
/*
* 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.fuelgauge.batterysaver;
import android.content.Context;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
/**
* Controller that update whether to turn on battery saver automatically
*/
public class AutoBatterySaverPreferenceController extends TogglePreferenceController implements
Preference.OnPreferenceChangeListener {
/**
* Default value for {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}.
*/
static final int DEFAULT_TRIGGER_LEVEL = 0;
/**
* The default value to set to {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL} when the
* user enables battery saver.
*/
private final int mDefaultTriggerLevelForOn;
@VisibleForTesting
static final String KEY_AUTO_BATTERY_SAVER = "auto_battery_saver";
public AutoBatterySaverPreferenceController(Context context) {
super(context, KEY_AUTO_BATTERY_SAVER);
mDefaultTriggerLevelForOn = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public boolean isChecked() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, DEFAULT_TRIGGER_LEVEL) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
BatterySaverUtils.setAutoBatterySaverTriggerLevel(mContext,
isChecked ? mDefaultTriggerLevelForOn : 0);
return true;
}
}

View File

@@ -1,166 +0,0 @@
/*
* 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.fuelgauge.batterysaver;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
/**
* Controller that update the battery saver seekbar
*/
public class AutoBatterySeekBarPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop, SeekBarPreference.OnPreferenceChangeListener {
private static final String TAG = "AutoBatterySeekBarPreferenceController";
private static final int INTERVAL = 5;
@VisibleForTesting
static final String KEY_AUTO_BATTERY_SEEK_BAR = "battery_saver_seek_bar";
private SeekBarPreference mPreference;
private AutoBatterySaverSettingObserver mContentObserver;
public AutoBatterySeekBarPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY_AUTO_BATTERY_SEEK_BAR);
mContentObserver = new AutoBatterySaverSettingObserver(new Handler(Looper.getMainLooper()));
if (lifecycle != null) {
lifecycle.addObserver(this);
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreference = (SeekBarPreference) screen.findPreference(
KEY_AUTO_BATTERY_SEEK_BAR);
mPreference.setContinuousUpdates(true);
mPreference.setAccessibilityRangeInfoType(
AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_PERCENT);
updatePreference(mPreference);
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
updatePreference(preference);
}
@Override
public void onStart() {
mContentObserver.registerContentObserver();
}
@Override
public void onStop() {
mContentObserver.unRegisterContentObserver();
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final int progress = (int) newValue;
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, progress * INTERVAL);
return true;
}
@VisibleForTesting
void updatePreference(Preference preference) {
final ContentResolver contentResolver = mContext.getContentResolver();
// Override the max value with LOW_POWER_MODE_TRIGGER_LEVEL_MAX, if set.
final int maxLevel = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0) / INTERVAL;
if (maxLevel > 0) {
if (!(preference instanceof SeekBarPreference)) {
Log.e(TAG, "Unexpected preference class: " + preference.getClass());
} else {
final SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
if (maxLevel < seekBarPreference.getMin()) {
Log.e(TAG, "LOW_POWER_MODE_TRIGGER_LEVEL_MAX too low; ignored.");
} else {
seekBarPreference.setMax(maxLevel);
}
}
}
// Set the current value.
final int level = Settings.Global.getInt(contentResolver,
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL,
AutoBatterySaverPreferenceController.DEFAULT_TRIGGER_LEVEL);
if (level == 0) {
preference.setVisible(false);
} else {
preference.setVisible(true);
preference.setTitle(mContext.getString(R.string.battery_saver_seekbar_title,
Utils.formatPercentage(level)));
SeekBarPreference seekBarPreference = (SeekBarPreference) preference;
seekBarPreference.setProgress(level / INTERVAL);
seekBarPreference.setSeekBarContentDescription(
mContext.getString(R.string.battery_saver_turn_on_automatically_title));
}
}
/**
* Observer that listens to change from {@link Settings.Global#LOW_POWER_MODE_TRIGGER_LEVEL}
*/
private final class AutoBatterySaverSettingObserver extends ContentObserver {
private final Uri mUri = Settings.Global.getUriFor(
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL);
private final ContentResolver mContentResolver;
public AutoBatterySaverSettingObserver(Handler handler) {
super(handler);
mContentResolver = mContext.getContentResolver();
}
public void registerContentObserver() {
mContentResolver.registerContentObserver(mUri, false, this);
}
public void unRegisterContentObserver() {
mContentResolver.unregisterContentObserver(this);
}
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
if (mUri.equals(uri)) {
updatePreference(mPreference);
}
}
}
}

View File

@@ -26,7 +26,13 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
/**
* Simple controller to navigate users to the scheduling page from
* "Settings > Battery > Battery Saver". Also updates the summary for preference based on
* the currently selected settings.
*/
public class BatterySaverSchedulePreferenceController extends BasePreferenceController {
@VisibleForTesting
@@ -36,6 +42,7 @@ public class BatterySaverSchedulePreferenceController extends BasePreferenceCont
public BatterySaverSchedulePreferenceController(Context context) {
super(context, KEY_BATTERY_SAVER_SCHEDULE);
BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
}
@Override

View File

@@ -0,0 +1,91 @@
/*
* 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.fuelgauge.batterysaver;
import android.content.ContentResolver;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
/**
* Responds to user actions in the Settings > Battery > Set a Schedule Screen
*
* Note that this is not a preference controller since that screen does not inherit from
* DashboardFragment.
*
* Will call the appropriate power manager APIs and modify the correct settings to enable
* users to control their automatic battery saver toggling preferences.
* See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
*/
public class BatterySaverScheduleRadioButtonsController {
public static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
public static final String KEY_ROUTINE = "key_battery_saver_routine";
public static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
private Context mContext;
private BatterySaverScheduleSeekBarController mSeekBarController;
public BatterySaverScheduleRadioButtonsController(Context context,
BatterySaverScheduleSeekBarController seekbar) {
mContext = context;
mSeekBarController = seekbar;
}
public String getDefaultKey() {
final ContentResolver resolver = mContext.getContentResolver();
// Note: this can also be obtained via PowerManager.getPowerSaveMode()
final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
// if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
// percentage mode, otherwise it is no schedule mode
if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
final int threshold =
Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
if (threshold <= 0) {
return KEY_NO_SCHEDULE;
}
return KEY_PERCENTAGE;
}
return KEY_ROUTINE;
}
public boolean setDefaultKey(String key) {
final ContentResolver resolver = mContext.getContentResolver();
switch(key) {
case KEY_NO_SCHEDULE:
Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
break;
case KEY_PERCENTAGE:
Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
break;
case KEY_ROUTINE:
Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_DYNAMIC);
break;
default:
throw new IllegalStateException(
"Not a valid key for " + this.getClass().getSimpleName());
}
mSeekBarController.updateSeekBar();
return true;
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.fuelgauge.batterysaver;
import android.content.ContentResolver;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.widget.SeekBarPreference;
/**
* Responds to user actions in the Settings > Battery > Set a Schedule Screen for the seekbar.
* Note that this seekbar is only visible when the radio button selected is "Percentage".
*
* Note that this is not a preference controller since that screen does not inherit from
* DashboardFragment.
*
* Will call the appropriate power manager APIs and modify the correct settings to enable
* users to control their automatic battery saver toggling preferences.
* See {@link Settings.Global#AUTOMATIC_POWER_SAVER_MODE} for more details.
*/
public class BatterySaverScheduleSeekBarController implements
OnPreferenceChangeListener {
public static final int MAX_SEEKBAR_VALUE = 15;
public static final int MIN_SEEKBAR_VALUE = 1;
public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
@VisibleForTesting
public SeekBarPreference mSeekBarPreference;
private Context mContext;
public BatterySaverScheduleSeekBarController(Context context) {
mContext = context;
mSeekBarPreference = new SeekBarPreference(context);
mSeekBarPreference.setOnPreferenceChangeListener(this);
mSeekBarPreference.setMax(BatterySaverScheduleSeekBarController.MAX_SEEKBAR_VALUE);
mSeekBarPreference.setMin(BatterySaverScheduleSeekBarController.MIN_SEEKBAR_VALUE);
mSeekBarPreference.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// The nits are in intervals of 5%
final int percentage = ((Integer) newValue) * 5;
Settings.Global.putInt(mContext.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL,
percentage);
preference.setTitle(mContext.getString(
R.string.battery_saver_seekbar_title, Utils.formatPercentage(percentage)));
return true;
}
public void updateSeekBar() {
final ContentResolver resolver = mContext.getContentResolver();
// Note: this can also be obtained via PowerManager.getPowerSaveMode()
final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
// if mode is "dynamic" we are in routine mode, percentage with non-zero threshold is
// percentage mode, otherwise it is no schedule mode
if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
final int threshold =
Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
if (threshold <= 0) {
mSeekBarPreference.setVisible(false);
} else {
mSeekBarPreference.setVisible(true);
mSeekBarPreference.setProgress(MIN_SEEKBAR_VALUE);
mSeekBarPreference.setTitle(mContext.getString(
R.string.battery_saver_seekbar_title,
Utils.formatPercentage(MIN_SEEKBAR_VALUE * 5)));
}
} else {
mSeekBarPreference.setVisible(false);
}
}
public void addToScreen(PreferenceScreen screen) {
screen.addPreference(mSeekBarPreference);
}
}

View File

@@ -18,48 +18,77 @@ package com.android.settings.fuelgauge.batterysaver;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.preference.PreferenceScreen;
import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settings.R;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.widget.CandidateInfo;
import com.google.common.collect.Lists;
import java.util.List;
/**
* Fragment that allows users to customize their automatic battery saver mode settings.
*
* Location: Settings > Battery > Battery Saver > Set a Schedule
* See {@link BatterySaverSchedulePreferenceController} for the controller that manages navigation
* to this screen from "Settings > Battery > Battery Saver" and the summary.
* See {@link BatterySaverScheduleRadioButtonsController} &
* {@link BatterySaverScheduleSeekBarController} for the controller that manages user
* interactions in this screen.
*/
public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
private static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
private static final String KEY_ROUTINE = "key_battery_saver_routine";
private static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
public static final int MAX_SEEKBAR_VALUE = 15;
public static final int MIN_SEEKBAR_VALUE = 1;
public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
public BatterySaverScheduleRadioButtonsController mRadioButtonController;
private BatterySaverScheduleSeekBarController mSeekBarController;
@Override
protected int getPreferenceScreenResId() {
return R.xml.battery_saver_schedule_settings;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mSeekBarController = new BatterySaverScheduleSeekBarController(context);
mRadioButtonController = new BatterySaverScheduleRadioButtonsController(
context, mSeekBarController);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected List<? extends CandidateInfo> getCandidates() {
Context context = getContext();
List<CandidateInfo> candidates = Lists.newArrayList();
String routineProviderApp = getContext().getResources()
.getString(com.android.internal.R.string.config_batterySaverScheduleProvider);
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_no_schedule),
/* summary */ null,
KEY_NO_SCHEDULE,
/* enabled */ true));
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_routine),
context.getText(R.string.battery_saver_auto_routine_summary),
KEY_ROUTINE,
BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE,
/* enabled */ true));
// only add routine option if an app has been specified
if (!TextUtils.isEmpty(routineProviderApp)) {
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_routine),
context.getText(R.string.battery_saver_auto_routine_summary),
BatterySaverScheduleRadioButtonsController.KEY_ROUTINE,
/* enabled */ true));
} else {
// Make sure routine is not selected if no provider app is configured
BatterySaverUtils.revertScheduleToNoneIfNeeded(context);
}
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_percentage),
/* summary */ null,
KEY_PERCENTAGE,
BatterySaverScheduleRadioButtonsController.KEY_PERCENTAGE,
/* enabled */ true));
return candidates;
@@ -79,22 +108,18 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
@Override
protected void addStaticPreferences(PreferenceScreen screen) {
SeekBarPreference seekbar = new SeekBarPreference(getContext());
seekbar.setMax(MAX_SEEKBAR_VALUE);
seekbar.setMin(MIN_SEEKBAR_VALUE);
seekbar.setTitle(R.string.battery_saver_seekbar_title_placeholder);
seekbar.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
screen.addPreference(seekbar);
mSeekBarController.updateSeekBar();
mSeekBarController.addToScreen(screen);
}
@Override
protected String getDefaultKey() {
return null;
return mRadioButtonController.getDefaultKey();
}
@Override
protected boolean setDefaultKey(String key) {
return false;
return mRadioButtonController.setDefaultKey(key);
}
@Override

View File

@@ -60,24 +60,11 @@ public class BatterySaverSettings extends DashboardFragment {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getSettingsLifecycle());
}
@Override
public int getHelpResource() {
return R.string.help_url_battery_saver_settings;
}
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context, Lifecycle lifecycle) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new AutoBatterySaverPreferenceController(context));
controllers.add(new AutoBatterySeekBarPreferenceController(context, lifecycle));
return controllers;
}
/**
* For Search.
*/
@@ -90,11 +77,5 @@ public class BatterySaverSettings extends DashboardFragment {
sir.xmlResId = R.xml.battery_saver_settings;
return Arrays.asList(sir);
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null);
}
};
}

View File

@@ -197,12 +197,11 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
}
Cursor getContextualCards() {
final SQLiteDatabase db = this.getReadableDatabase();
final SQLiteDatabase db = getReadableDatabase();
final String selection = CardColumns.CARD_DISMISSED + "=0";
Cursor cursor = db.query(CARD_TABLE, null /* columns */, selection,
return db.query(CARD_TABLE, null /* columns */, selection,
null /* selectionArgs */, null /* groupBy */, null /* having */,
CardColumns.SCORE + " DESC" /* orderBy */);
return cursor;
}
/**

View File

@@ -1,108 +0,0 @@
/*
* 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.homepage.contextualcards.conditional;
import android.content.Context;
import android.os.PowerManager;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.fuelgauge.BatterySaverReceiver;
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
import com.android.settings.homepage.contextualcards.ContextualCard;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import java.util.Objects;
public class BatterySaverConditionController implements ConditionalCardController,
BatterySaverReceiver.BatterySaverListener {
static final int ID = Objects.hash("BatterySaverConditionController");
private final Context mAppContext;
private final ConditionManager mConditionManager;
private final BatterySaverReceiver mReceiver;
private final PowerManager mPowerManager;
public BatterySaverConditionController(Context appContext, ConditionManager conditionManager) {
mAppContext = appContext;
mConditionManager = conditionManager;
mPowerManager = appContext.getSystemService(PowerManager.class);
mReceiver = new BatterySaverReceiver(appContext);
mReceiver.setBatterySaverListener(this);
}
@Override
public long getId() {
return ID;
}
@Override
public boolean isDisplayable() {
return mPowerManager.isPowerSaveMode();
}
@Override
public void onPrimaryClick(Context context) {
new SubSettingLauncher(context)
.setDestination(BatterySaverSettings.class.getName())
.setSourceMetricsCategory(MetricsProto.MetricsEvent.DASHBOARD_SUMMARY)
.setTitleRes(R.string.battery_saver)
.launch();
}
@Override
public void onActionClick() {
BatterySaverUtils.setPowerSaveMode(mAppContext, false,
/*needFirstTimeWarning*/ false);
}
@Override
public ContextualCard buildContextualCard() {
return new ConditionalContextualCard.Builder()
.setConditionId(ID)
.setMetricsConstant(MetricsProto.MetricsEvent.SETTINGS_CONDITION_BATTERY_SAVER)
.setActionText(mAppContext.getText(R.string.condition_turn_off))
.setName(mAppContext.getPackageName() + "/"
+ mAppContext.getText(R.string.condition_battery_title))
.setTitleText(mAppContext.getText(R.string.condition_battery_title).toString())
.setSummaryText(mAppContext.getText(R.string.condition_battery_summary).toString())
.setIconDrawable(mAppContext.getDrawable(R.drawable.ic_battery_saver_accent_24dp))
.setIsHalfWidth(true)
.build();
}
@Override
public void startMonitoringStateChange() {
mReceiver.setListening(true);
}
@Override
public void stopMonitoringStateChange() {
mReceiver.setListening(false);
}
@Override
public void onPowerSaveModeChanged() {
mConditionManager.onConditionChanged();
}
@Override
public void onBatteryChanged(boolean pluggedIn) {
}
}

View File

@@ -154,7 +154,6 @@ public class ConditionManager {
mCardControllers.add(new AirplaneModeConditionController(mAppContext, this /* manager */));
mCardControllers.add(
new BackgroundDataConditionController(mAppContext, this /* manager */));
mCardControllers.add(new BatterySaverConditionController(mAppContext, this /* manager */));
mCardControllers.add(new CellularDataConditionController(mAppContext, this /* manager */));
mCardControllers.add(new DndConditionCardController(mAppContext, this /* manager */));
mCardControllers.add(new HotspotConditionController(mAppContext, this /* manager */));

View File

@@ -19,18 +19,55 @@ package com.android.settings.network;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
// This controls a header at the top of the Network & internet page that only appears when there
// are two or more active mobile subscriptions. It shows an overview of available network
// connections with an entry for wifi (if connected) and an entry for each subscription.
public class MultiNetworkHeaderController extends BasePreferenceController {
public class MultiNetworkHeaderController extends BasePreferenceController implements
SubscriptionsPreferenceController.UpdateListener {
public static final String TAG = "MultiNetworkHdrCtrl";
private SubscriptionsPreferenceController mSubscriptionsController;
private PreferenceCategory mPreferenceCategory;
public MultiNetworkHeaderController(Context context, String key) {
super(context, key);
super(context, key);
}
public void init(Lifecycle lifecycle) {
mSubscriptionsController = createSubscriptionsController(lifecycle);
// TODO(asargent) - add in a controller for showing wifi status here
}
@VisibleForTesting
SubscriptionsPreferenceController createSubscriptionsController(Lifecycle lifecycle) {
return new SubscriptionsPreferenceController(mContext, lifecycle, this, mPreferenceKey, 10);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = (PreferenceCategory) screen.findPreference(mPreferenceKey);
mPreferenceCategory.setVisible(isAvailable());
mSubscriptionsController.displayPreference(screen);
}
@Override
public int getAvailabilityStatus() {
return UNSUPPORTED_ON_DEVICE;
if (mSubscriptionsController == null || !mSubscriptionsController.isAvailable()) {
return CONDITIONALLY_UNAVAILABLE;
} else {
return AVAILABLE;
}
}
@Override
public void onChildrenUpdated() {
mPreferenceCategory.setVisible(isAvailable());
}
}

View File

@@ -72,6 +72,9 @@ public class NetworkDashboardFragment extends DashboardFragment implements
public void onAttach(Context context) {
super.onAttach(context);
if (FeatureFlagUtils.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) {
use(MultiNetworkHeaderController.class).init(getSettingsLifecycle());
}
use(AirplaneModePreferenceController.class).setFragment(this);
}

View File

@@ -24,8 +24,20 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import androidx.annotation.VisibleForTesting;
public class SubscriptionUtil {
private static List<SubscriptionInfo> sResultsForTesting;
@VisibleForTesting
static void setAvailableSubscriptionsForTesting(List<SubscriptionInfo> results) {
sResultsForTesting = results;
}
public static List<SubscriptionInfo> getAvailableSubscriptions(SubscriptionManager manager) {
if (sResultsForTesting != null) {
return sResultsForTesting;
}
List<SubscriptionInfo> subscriptions = manager.getAvailableSubscriptionInfoList();
if (subscriptions == null) {
subscriptions = new ArrayList<>();

View File

@@ -0,0 +1,183 @@
/*
* 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.network;
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settings.R;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Map;
import androidx.collection.ArrayMap;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
/**
* This manages a set of Preferences it places into a PreferenceGroup owned by some parent
* controller class - one for each available subscription. This controller is only considered
* available if there are 2 or more subscriptions.
*/
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
private static final String TAG = "SubscriptionsPrefCntrlr";
private UpdateListener mUpdateListener;
private String mPreferenceGroupKey;
private PreferenceGroup mPreferenceGroup;
private SubscriptionManager mManager;
private SubscriptionsChangeListener mSubscriptionsListener;
// Map of subscription id to Preference
private Map<Integer, Preference> mSubscriptionPreferences;
private int mStartOrder;
/**
* This interface lets a parent of this class know that some change happened - this could
* either be because overall availability changed, or because we've added/removed/updated some
* preferences.
*/
public interface UpdateListener {
void onChildrenUpdated();
}
/**
* @param context the context for the UI where we're placing these preferences
* @param lifecycle for listening to lifecycle events for the UI
* @param updateListener called to let our parent controller know that our availability has
* changed, or that one or more of the preferences we've placed in the
* PreferenceGroup has changed
* @param preferenceGroupKey the key used to lookup the PreferenceGroup where Preferences will
* be placed
* @param startOrder the order that should be given to the first Preference placed into
* the PreferenceGroup; the second will use startOrder+1, third will
* use startOrder+2, etc. - this is useful for when the parent wants
* to have other preferences in the same PreferenceGroup and wants
* a specific ordering relative to this controller's prefs.
*/
public SubscriptionsPreferenceController(Context context, Lifecycle lifecycle,
UpdateListener updateListener, String preferenceGroupKey, int startOrder) {
super(context);
mUpdateListener = updateListener;
mPreferenceGroupKey = preferenceGroupKey;
mStartOrder = startOrder;
mManager = context.getSystemService(SubscriptionManager.class);
mSubscriptionPreferences = new ArrayMap<>();
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mSubscriptionsListener.start();
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
mSubscriptionsListener.stop();
}
@Override
public void displayPreference(PreferenceScreen screen) {
mPreferenceGroup = (PreferenceGroup) screen.findPreference(mPreferenceGroupKey);
update();
}
private void update() {
if (mPreferenceGroup == null) {
return;
}
if (mSubscriptionsListener.isAirplaneModeOn()) {
for (Preference pref : mSubscriptionPreferences.values()) {
mPreferenceGroup.removePreference(pref);
}
mSubscriptionPreferences.clear();
mUpdateListener.onChildrenUpdated();
return;
}
final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
mSubscriptionPreferences = new ArrayMap<>();
int order = mStartOrder;
for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mManager) ) {
final int subId = info.getSubscriptionId();
Preference pref = existingPrefs.remove(subId);
if (pref == null) {
pref = new Preference(mPreferenceGroup.getContext());
mPreferenceGroup.addPreference(pref);
}
pref.setTitle(info.getDisplayName());
pref.setIcon(R.drawable.ic_network_cell);
pref.setOrder(order++);
// TODO(asargent) - set summary here to indicate default for calls/sms and data
pref.setOnPreferenceClickListener(clickedPref -> {
// TODO(asargent) - make this start MobileNetworkActivity once we've
// added support for it to take a subscription id
return true;
});
mSubscriptionPreferences.put(subId, pref);
}
// Remove any old preferences that no longer map to a subscription.
for (Preference pref : existingPrefs.values()) {
mPreferenceGroup.removePreference(pref);
}
mUpdateListener.onChildrenUpdated();
}
/**
*
* @return true if there are at least 2 available subscriptions.
*/
@Override
public boolean isAvailable() {
if (mSubscriptionsListener.isAirplaneModeOn()) {
return false;
}
return SubscriptionUtil.getAvailableSubscriptions(mManager).size() >= 2;
}
@Override
public String getPreferenceKey() {
return null;
}
@Override
public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
update();
}
@Override
public void onSubscriptionsChanged() {
update();
}
}

View File

@@ -21,6 +21,8 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
@@ -82,33 +84,47 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
return intent;
}
public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
if (si == null || si.metaData == null) {
public static ZenRuleInfo getRuleInfo(PackageManager pm, ComponentInfo ci) {
if (ci == null || ci.metaData == null) {
return null;
}
final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
final ComponentName configurationActivity = getSettingsActivity(si);
final String ruleType = (ci instanceof ServiceInfo)
? ci.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE)
: ci.metaData.getString(NotificationManager.META_DATA_AUTOMATIC_RULE_TYPE);
final ComponentName configurationActivity = getSettingsActivity(null, ci);
if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
final ZenRuleInfo ri = new ZenRuleInfo();
ri.serviceComponent = new ComponentName(si.packageName, si.name);
ri.serviceComponent =
(ci instanceof ServiceInfo) ? new ComponentName(ci.packageName, ci.name) : null;
ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
ri.title = ruleType;
ri.packageName = si.packageName;
ri.configurationActivity = getSettingsActivity(si);
ri.packageLabel = si.applicationInfo.loadLabel(pm);
ri.ruleInstanceLimit =
si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
ri.packageName = ci.packageName;
ri.configurationActivity = configurationActivity;
ri.packageLabel = ci.applicationInfo.loadLabel(pm);
ri.ruleInstanceLimit = (ci instanceof ServiceInfo)
? ci.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1)
: ci.metaData.getInt(NotificationManager.META_DATA_RULE_INSTANCE_LIMIT, -1);
return ri;
}
return null;
}
protected static ComponentName getSettingsActivity(ServiceInfo si) {
if (si == null || si.metaData == null) {
protected static ComponentName getSettingsActivity(AutomaticZenRule rule, ComponentInfo ci) {
// prefer config activity on the rule itself; fallback to manifest definition
if (rule != null && rule.getConfigurationActivity() != null) {
return rule.getConfigurationActivity();
}
if (ci == null) {
return null;
}
// new activity backed rule
if (ci instanceof ActivityInfo) {
return new ComponentName(ci.packageName, ci.name);
}
// old service backed rule
final String configurationActivity =
si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
ci.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
if (configurationActivity != null) {
return ComponentName.unflattenFromString(configurationActivity);
}
@@ -127,7 +143,7 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent,
mRuleInfo.defaultConditionId,
mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
String savedRuleId = mBackend.addZenRule(rule);
if (savedRuleId != null) {

View File

@@ -18,6 +18,7 @@ package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
@@ -92,6 +93,7 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
return new ManagedServiceSettings.Config.Builder()
.setTag(TAG)
.setIntentAction(ConditionProviderService.SERVICE_INTERFACE)
.setConfigurationIntentAction(NotificationManager.ACTION_AUTOMATIC_ZEN_RULE)
.setPermission(android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE)
.setNoun("condition provider")
.build();

View File

@@ -24,6 +24,8 @@ public class ZenRuleInfo {
that.defaultConditionId) : that.defaultConditionId != null) return false;
if (serviceComponent != null ? !serviceComponent.equals(
that.serviceComponent) : that.serviceComponent != null) return false;
if (id != null ? !id.equals(that.id) : that.id != null)
return false;
return packageLabel != null ? packageLabel.equals(
that.packageLabel) : that.packageLabel == null;
@@ -38,4 +40,5 @@ public class ZenRuleInfo {
public boolean isSystem;
public CharSequence packageLabel;
public int ruleInstanceLimit = -1;
public String id;
}

View File

@@ -21,6 +21,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.service.notification.ZenModeConfig;
@@ -45,7 +46,6 @@ public class ZenRulePreference extends TwoTargetPreference {
private static final ManagedServiceSettings.Config CONFIG =
ZenModeAutomationSettings.getConditionProviderConfig();
final String mId;
boolean appExists;
final Fragment mParent;
final Preference mPref;
final Context mContext;
@@ -56,7 +56,6 @@ public class ZenRulePreference extends TwoTargetPreference {
final AutomaticZenRule mRule;
CharSequence mName;
private boolean mIsSystemRule;
private Intent mIntent;
private boolean mChecked;
private CheckBox mCheckBox;
@@ -163,25 +162,17 @@ public class ZenRulePreference extends TwoTargetPreference {
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
rule.getConditionId(), true);
final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
mIsSystemRule = isSchedule || isEvent;
try {
ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
setSummary(computeRuleSummary(rule));
} catch (PackageManager.NameNotFoundException e) {
appExists = false;
return;
}
setSummary(computeRuleSummary(rule));
appExists = true;
setTitle(mName);
setPersistent(false);
final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
: isEvent ? ZenModeEventRuleSettings.ACTION : "";
ServiceInfo si = mServiceListing.findService(rule.getOwner());
ComponentInfo si = mServiceListing.findService(rule.getOwner());
ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
getSettingsActivity(si);
getSettingsActivity(rule, si);
mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
settingsActivity, mId);
setKey(mId);

View File

@@ -23,6 +23,7 @@ import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
@@ -192,16 +193,17 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
private final ZenServiceListing.Callback mServiceListingCallback = new
ZenServiceListing.Callback() {
@Override
public void onServicesReloaded(Set<ServiceInfo> services) {
if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
public void onComponentsReloaded(Set<ComponentInfo> componentInfos) {
if (DEBUG) Log.d(TAG, "Reloaded: count=" + componentInfos.size());
Set<ZenRuleInfo> externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
for (ServiceInfo serviceInfo : services) {
for (ComponentInfo ci : componentInfos) {
final ZenRuleInfo ri = AbstractZenModeAutomaticRulePreferenceController.
getRuleInfo(mPm, serviceInfo);
getRuleInfo(mPm, ci);
if (ri != null && ri.configurationActivity != null
&& mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
&& (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit
>= (mNm.getRuleInstanceCount(serviceInfo.getComponentName()) + 1))) {
>= (mNm.getRuleInstanceCount(ci.getComponentName()) + 1))) {
externalRuleTypes.add(ri);
}
}

View File

@@ -23,6 +23,7 @@ import android.util.Log;
import com.android.settings.R;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -111,6 +112,8 @@ public abstract class FeatureFactory {
public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
public abstract FaceFeatureProvider getFaceFeatureProvider();
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);

View File

@@ -28,6 +28,8 @@ import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.accounts.AccountFeatureProviderImpl;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProviderImpl;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProviderImpl;
import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl;
import com.android.settings.core.instrumentation.SettingsMetricsFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
@@ -78,6 +80,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
private AccountFeatureProvider mAccountFeatureProvider;
private PanelFeatureProvider mPanelFeatureProvider;
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
private FaceFeatureProvider mFaceFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -224,10 +227,19 @@ public class FeatureFactoryImpl extends FeatureFactory {
return mPanelFeatureProvider;
}
@Override
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
if (mContextualCardFeatureProvider == null) {
mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
}
return mContextualCardFeatureProvider;
}
@Override
public FaceFeatureProvider getFaceFeatureProvider() {
if (mFaceFeatureProvider == null) {
mFaceFeatureProvider = new FaceFeatureProviderImpl();
}
return mFaceFeatureProvider;
}
}

View File

@@ -240,9 +240,11 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
public final int warningDialogTitle;
public final int warningDialogSummary;
public final int emptyText;
public final String configIntentAction;
private Config(String tag, String setting, String intentAction, String permission,
String noun, int warningDialogTitle, int warningDialogSummary, int emptyText) {
private Config(String tag, String setting, String intentAction, String configIntentAction,
String permission, String noun, int warningDialogTitle, int warningDialogSummary,
int emptyText) {
this.tag = tag;
this.setting = setting;
this.intentAction = intentAction;
@@ -251,6 +253,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
this.warningDialogTitle = warningDialogTitle;
this.warningDialogSummary = warningDialogSummary;
this.emptyText = emptyText;
this.configIntentAction = configIntentAction;
}
public static class Builder{
@@ -262,6 +265,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
private int mWarningDialogTitle;
private int mWarningDialogSummary;
private int mEmptyText;
private String mConfigIntentAction;
public Builder setTag(String tag) {
mTag = tag;
@@ -278,6 +282,11 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
return this;
}
public Builder setConfigurationIntentAction(String action) {
mConfigIntentAction = action;
return this;
}
public Builder setPermission(String permission) {
mPermission = permission;
return this;
@@ -304,8 +313,8 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings {
}
public Config build() {
return new Config(mTag, mSetting, mIntentAction, mPermission, mNoun,
mWarningDialogTitle, mWarningDialogSummary, mEmptyText);
return new Config(mTag, mSetting, mIntentAction, mConfigIntentAction, mPermission,
mNoun, mWarningDialogTitle, mWarningDialogSummary, mEmptyText);
}
}
}

View File

@@ -20,6 +20,8 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -34,7 +36,7 @@ public class ZenServiceListing {
private final Context mContext;
private final ManagedServiceSettings.Config mConfig;
private final Set<ServiceInfo> mApprovedServices = new ArraySet<ServiceInfo>();
private final Set<ComponentInfo> mApprovedComponents = new ArraySet<>();
private final List<Callback> mZenCallbacks = new ArrayList<>();
private final NotificationManager mNm;
@@ -44,11 +46,14 @@ public class ZenServiceListing {
mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
public ServiceInfo findService(final ComponentName cn) {
for (ServiceInfo service : mApprovedServices) {
final ComponentName serviceCN = new ComponentName(service.packageName, service.name);
if (serviceCN.equals(cn)) {
return service;
public ComponentInfo findService(final ComponentName cn) {
if (cn == null) {
return null;
}
for (ComponentInfo component : mApprovedComponents) {
final ComponentName ci = new ComponentName(component.packageName, component.name);
if (ci.equals(cn)) {
return component;
}
}
return null;
@@ -63,32 +68,29 @@ public class ZenServiceListing {
}
public void reloadApprovedServices() {
mApprovedServices.clear();
mApprovedComponents.clear();
List<String> enabledNotificationListenerPkgs = mNm.getEnabledNotificationListenerPackages();
List<ServiceInfo> services = new ArrayList<>();
getServices(mConfig, services, mContext.getPackageManager());
for (ServiceInfo service : services) {
final String servicePackage = service.getComponentName().getPackageName();
if (mNm.isNotificationPolicyAccessGrantedForPackage(servicePackage)
|| enabledNotificationListenerPkgs.contains(servicePackage)) {
mApprovedServices.add(service);
List<ComponentInfo> components = new ArrayList<>();
getServices(mConfig, components, mContext.getPackageManager());
getActivities(mConfig, components, mContext.getPackageManager());
for (ComponentInfo componentInfo : components) {
final String pkg = componentInfo.getComponentName().getPackageName();
if (mNm.isNotificationPolicyAccessGrantedForPackage(pkg)
|| enabledNotificationListenerPkgs.contains(pkg)) {
mApprovedComponents.add(componentInfo);
}
}
if (!mApprovedServices.isEmpty()) {
if (!mApprovedComponents.isEmpty()) {
for (Callback callback : mZenCallbacks) {
callback.onServicesReloaded(mApprovedServices);
callback.onComponentsReloaded(mApprovedComponents);
}
}
}
private static int getServices(ManagedServiceSettings.Config c, List<ServiceInfo> list,
private static void getServices(ManagedServiceSettings.Config c, List<ComponentInfo> list,
PackageManager pm) {
int services = 0;
if (list != null) {
list.clear();
}
final int user = ActivityManager.getCurrentUser();
List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
@@ -110,12 +112,28 @@ public class ZenServiceListing {
if (list != null) {
list.add(info);
}
services++;
}
return services;
}
private static void getActivities(ManagedServiceSettings.Config c, List<ComponentInfo> list,
PackageManager pm) {
final int user = ActivityManager.getCurrentUser();
List<ResolveInfo> resolveInfos = pm.queryIntentActivitiesAsUser(
new Intent(c.configIntentAction),
PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
user);
for (int i = 0, count = resolveInfos.size(); i < count; i++) {
ResolveInfo resolveInfo = resolveInfos.get(i);
ActivityInfo info = resolveInfo.activityInfo;
if (list != null) {
list.add(info);
}
}
}
public interface Callback {
void onServicesReloaded(Set<ServiceInfo> services);
void onComponentsReloaded(Set<ComponentInfo> components);
}
}

View File

@@ -73,7 +73,7 @@ public class AddNetworkFragment extends InstrumentedFragment implements WifiConf
scannerButton.setOnClickListener((View v) -> {
// Launch QR code scanner to join a network.
getContext().startActivity(
WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
});
}
}

View File

@@ -86,9 +86,13 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
if (scannerButton != null) {
scannerButton.setVisibility(View.VISIBLE);
scannerButton.setOnClickListener((View v) -> {
String ssid = null;
if (mAccessPoint != null) {
ssid = mAccessPoint.getSsidStr();
}
// Launch QR code scanner to join a network.
getContext().startActivity(
WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
WifiDppUtils.getEnrolleeQrCodeScannerIntent(ssid));
});
}
}

View File

@@ -244,7 +244,7 @@ public class WifiSettings extends RestrictedSettingsFragment
mAddPreference.setButtonOnClickListener((View v) -> {
// Launch QR code scanner to join a network.
getContext().startActivity(
WifiDppUtils.getConfiguratorQRCodeScannerIntent(/* ssid */ null));
WifiDppUtils.getEnrolleeQrCodeScannerIntent(/* ssid */ null));
});
}
mStatusMessagePreference = (LinkablePreference) findPreference(PREF_KEY_STATUS_MESSAGE);

View File

@@ -549,11 +549,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
* Show QR code to share the network represented by this preference.
*/
public void launchQRCodeGenerator() {
final Intent intent = new Intent(
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY,
Intent intent = WifiDppUtils.getConfiguratorQrCodeGeneratorIntent(mAccessPoint.getSsidStr(),
mAccessPoint.getSecurityString(/* concise */ false));
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
mContext.startActivity(intent);
}

View File

@@ -35,7 +35,7 @@ import com.android.settings.R;
* To provision "this" device with specified Wi-Fi network.
*
* To use intent action {@code ACTION_ENROLLEE_QR_CODE_SCANNER}, specify the SSID string of the
* Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_QR_CODE}.
* Wi-Fi network to be provisioned in {@code WifiDppUtils.EXTRA_WIFI_SSID}.
*/
public class WifiDppEnrolleeActivity extends InstrumentedActivity {
private static final String TAG = "WifiDppEnrolleeActivity";

View File

@@ -18,7 +18,6 @@ package com.android.settings.wifi.dpp;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -30,11 +29,10 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.wifi.qrcode.QrDecorateView;
import com.android.settings.R;
/**
* TODO: Should refine code to only initiate UI component in each child fragment.
* TODO: b/120645817 should refine code to only initiate UI component in each child fragment.
*/
/**
@@ -50,14 +48,8 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private TextView mTitle;
private TextView mDescription;
private SurfaceView mPreviewView; //optional, for WifiDppQrCodeScannerFragment
private QrDecorateView mDecorateViiew; //optional, for WifiDppQrCodeScannerFragment
private TextView mErrorMessage; //optional, for WifiDppQrCodeScannerFragment
private ImageView mBarcodeView; //optional, for WifiDppQrCodeGeneratorFragment
private ListView mSavedWifiNetworkList; //optional, for WifiDppChooseSavedWifiNetworkFragment
private ProgressBar mProgressBar; //optional, for WifiDppAddDeviceFragment
private ImageView mWifiApPictureView; //optional, for WifiDppAddDeviceFragment
private TextView mChooseDifferentNetwork;//optional, for WifiDppAddDeviceFragment
@@ -91,13 +83,8 @@ public abstract class WifiDppQrCodeBaseFragment extends InstrumentedFragment {
private void initView(View view) {
mTitle = view.findViewById(R.id.title);
mDescription = view.findViewById(R.id.description);
mPreviewView = view.findViewById(R.id.preview_view);
mDecorateViiew = view.findViewById(R.id.decorate_view);
mErrorMessage = view.findViewById(R.id.error_message);
mBarcodeView = view.findViewById(R.id.barcode_view);
mSavedWifiNetworkList = view.findViewById(R.id.saved_wifi_network_list);
mProgressBar = view.findViewById(R.id.progress_bar);

View File

@@ -21,13 +21,16 @@ import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Size;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;
import android.view.View;
import com.android.settings.R;
@@ -35,10 +38,10 @@ import com.android.settings.wifi.qrcode.QrCamera;
import com.android.settings.wifi.qrcode.QrDecorateView;
public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment implements
SurfaceHolder.Callback,
SurfaceTextureListener,
QrCamera.ScannerCallback {
private QrCamera mCamera;
private SurfaceView mSurfaceView;
private TextureView mTextureView;
private QrDecorateView mDecorateView;
/** true if the fragment working for configurator, false enrollee*/
@@ -87,7 +90,14 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
setDescription(getString(R.string.wifi_dpp_center_qr_code, wifiNetworkConfig.getSsid()));
} else {
setTitle(getString(R.string.wifi_dpp_scan_qr_code));
setDescription(getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid));
String description;
if (TextUtils.isEmpty(mSsid)) {
description = getString(R.string.wifi_dpp_scan_qr_code_join_unknown_network, mSsid);
} else {
description = getString(R.string.wifi_dpp_scan_qr_code_join_network, mSsid);
}
setDescription(description);
}
ActionBar actionBar = getActivity().getActionBar();
@@ -101,22 +111,12 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSurfaceView = (SurfaceView) view.findViewById(R.id.preview_view);
final SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceHolder.addCallback(this);
mTextureView = (TextureView) view.findViewById(R.id.preview_view);
mTextureView.setSurfaceTextureListener(this);
mDecorateView = (QrDecorateView) view.findViewById(R.id.decorate_view);
}
@Override
public void onDestroyView() {
SurfaceHolder surfaceHolder = mSurfaceView.getHolder();
surfaceHolder.removeCallback(this);
super.onDestroyView();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.removeItem(Menu.FIRST);
@@ -125,23 +125,29 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
}
@Override
public void surfaceCreated(final SurfaceHolder holder) {
initCamera(holder);
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
initCamera(surface);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Do nothing
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
destroyCamera();
return true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Do nothing
}
@Override
public Size getViewSize() {
return new Size(mSurfaceView.getWidth(), mSurfaceView.getHeight());
return new Size(mTextureView.getWidth(), mTextureView.getHeight());
}
@Override
@@ -149,6 +155,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
return new Rect(0, 0, previewSize.getHeight(), previewSize.getHeight());
}
@Override
public void setTransform(Matrix transform) {
mTextureView.setTransform(transform);
}
@Override
public void handleSuccessfulResult(String qrCode) {
destroyCamera();
@@ -161,11 +172,11 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl
destroyCamera();
}
private void initCamera(SurfaceHolder holder) {
private void initCamera(SurfaceTexture surface) {
// Check if the camera has already created.
if (mCamera == null) {
mCamera = new QrCamera(getContext(), this);
mCamera.start(holder);
mCamera.start(surface);
}
}

View File

@@ -88,14 +88,14 @@ public class WifiDppUtils {
}
/**
* Returns an intent to launch QR code scanner.
* Returns an intent to launch QR code scanner for Wi-Fi DPP enrollee.
*
* @param ssid The data corresponding to {@code WifiConfiguration} SSID
* @return Intent for launching QR code scanner
*/
public static Intent getConfiguratorQRCodeScannerIntent(String ssid) {
public static Intent getEnrolleeQrCodeScannerIntent(String ssid) {
final Intent intent = new Intent(
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_SCANNER);
WifiDppEnrolleeActivity.ACTION_ENROLLEE_QR_CODE_SCANNER);
if (!TextUtils.isEmpty(ssid)) {
intent.putExtra(EXTRA_WIFI_SSID, ssid);
}
@@ -109,7 +109,8 @@ public class WifiDppUtils {
* @param Security The data is from {@code AccessPoint.securityToString}
* @return Intent for launching QR code generator
*/
public static Intent getConfiguratorQRCodeGeneratorIntent(String ssid, String Security) {
public static Intent getConfiguratorQrCodeGeneratorIntent(String ssid, String Security) {
//TODO: b/118794858#comment6 should put password & hideSsid in intent extra
final Intent intent = new Intent(
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
if (!TextUtils.isEmpty(ssid)) {

View File

@@ -17,7 +17,10 @@
package com.android.settings.wifi.qrcode;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Parameters;
@@ -29,7 +32,6 @@ import android.util.ArrayMap;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
@@ -50,7 +52,7 @@ import androidx.annotation.VisibleForTesting;
/**
* Manage the camera for the QR scanner and help the decoder to get the image inside the scanning
* frame. Caller prepares a {@link SurfaceHolder} then call {@link #start(SurfaceHolder)} to
* frame. Caller prepares a {@link SurfaceTexture} then call {@link #start(SurfaceTexture)} to
* start QR Code scanning. The scanning result will return by ScannerCallback interface. Caller
* can also call {@link #stop()} to halt QR Code scanning before the result returned.
*/
@@ -90,12 +92,11 @@ public class QrCamera extends Handler {
* The function start camera preview and capture pictures to decode QR code continuously in a
* background task.
*
* @param surfaceHolder the Surface to be used for live preview, must already contain a surface
* when this method is called.
* @param surface The surface to be used for live preview.
*/
public void start(SurfaceHolder surfaceHolder) {
public void start(SurfaceTexture surface) {
if (mDecodeTask == null) {
mDecodeTask = new DecodingTask(surfaceHolder);
mDecodeTask = new DecodingTask(surface);
// Execute in the separate thread pool to prevent block other AsyncTask.
mDecodeTask.executeOnExecutor(Executors.newSingleThreadExecutor());
}
@@ -144,6 +145,13 @@ public class QrCamera extends Handler {
* @return The rectangle would like to crop from the camera preview shot.
*/
Rect getFramePosition(Size previewSize, int cameraOrientation);
/**
* Sets the transform to associate with preview area.
*
* @param transform The transform to apply to the content of preview
*/
void setTransform(Matrix transform);
}
private void setCameraParameter() {
@@ -200,15 +208,15 @@ public class QrCamera extends Handler {
private class DecodingTask extends AsyncTask<Void, Void, String> {
private QrYuvLuminanceSource mImage;
private SurfaceHolder mSurfaceHolder;
private SurfaceTexture mSurface;
private DecodingTask(SurfaceHolder surfaceHolder) {
mSurfaceHolder = surfaceHolder;
private DecodingTask(SurfaceTexture surface) {
mSurface = surface;
}
@Override
protected String doInBackground(Void... tmp) {
if (!initCamera(mSurfaceHolder)) {
if (!initCamera(mSurface)) {
return null;
}
@@ -253,7 +261,7 @@ public class QrCamera extends Handler {
}
}
private boolean initCamera(SurfaceHolder surfaceHolder) {
private boolean initCamera(SurfaceTexture surface) {
final int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
try {
@@ -261,7 +269,7 @@ public class QrCamera extends Handler {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
mCamera = Camera.open(i);
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setPreviewTexture(surface);
mCameraOrientation = cameraInfo.orientation;
break;
}
@@ -272,6 +280,7 @@ public class QrCamera extends Handler {
return false;
}
setCameraParameter();
setTransformationMatrix(mScannerCallback.getViewSize());
if (!startPreview()) {
Log.e(TAG, "Error to init Camera");
mCamera = null;
@@ -288,6 +297,36 @@ public class QrCamera extends Handler {
}
}
/** Set transfom matrix to crop and center the preview picture */
private void setTransformationMatrix(Size viewSize) {
// Check aspect ratio, can only handle square view.
final int viewRatio = (int)getRatio(viewSize.getWidth(), viewSize.getHeight());
if (viewRatio != 1) {
throw new IllegalArgumentException("Preview area should be square");
}
final boolean isPortrait = mContext.get().getResources().getConfiguration().orientation
== Configuration.ORIENTATION_PORTRAIT ? true : false;
final int previewWidth = isPortrait ? mPreviewSize.getWidth() : mPreviewSize.getHeight();
final int previewHeight = isPortrait ? mPreviewSize.getHeight() : mPreviewSize.getWidth();
final float ratioPreview = (float) getRatio(previewWidth, previewHeight);
// Calculate transformation matrix.
float scaleX = 1.0f;
float scaleY = 1.0f;
if (previewWidth > previewHeight) {
scaleY = scaleX / ratioPreview;
} else {
scaleX = scaleY / ratioPreview;
}
// Set the transform matrix.
final Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY);
mScannerCallback.setTransform(matrix);
}
private QrYuvLuminanceSource getFrameImage(byte[] imageData) {
final Rect frame = mScannerCallback.getFramePosition(mPreviewSize, mCameraOrientation);
final Camera.Size size = mParameters.getPictureSize();

View File

@@ -0,0 +1,50 @@
/*
* 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.wifi.qrcode;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
/**
* A customize square {@link FrameLayout}.
* This is used for camera preview. Choose the smaller size of both dimensions as length and width.
*/
public class QrPreviewLayout extends FrameLayout {
public QrPreviewLayout(Context context) {
super(context);
}
public QrPreviewLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public QrPreviewLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// Choose the smaller size of the two dimensions.
if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) {
super.onMeasure(heightMeasureSpec, heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
}

View File

@@ -7,7 +7,7 @@ LOCAL_CERTIFICATE := platform
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
androidx.test.rules \
mockito-target \
ub-uiautomator \
truth-prebuilt \

View File

@@ -44,7 +44,7 @@
</application>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings"
android:label="Settings Test Cases">
</instrumentation>

View File

@@ -19,13 +19,14 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
import android.text.format.DateUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -19,13 +19,14 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
import android.text.format.DateUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -7,7 +7,6 @@ com.android.settings.bluetooth.BluetoothDeviceNamePreferenceController
com.android.settings.bluetooth.BluetoothDeviceRenamePreferenceController
com.android.settings.datausage.DataUsageSummaryPreferenceController
com.android.settings.fuelgauge.RestrictAppPreferenceController
com.android.settings.fuelgauge.batterysaver.AutoBatterySeekBarPreferenceController
com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceController
com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController
com.android.settings.security.VisiblePatternProfilePreferenceController

View File

@@ -58,6 +58,9 @@
<bool name="config_show_system_update_settings">false</bool>
<bool name="config_wifi_support_connected_mac_randomization">false</bool>
<bool name="config_show_device_model">false</bool>
<bool name="config_show_top_level_battery">false</bool>
<bool name="config_show_top_level_connected_devices">false</bool>
<bool name="config_show_top_level_display">false</bool>
<bool name="config_show_wifi_ip_address">false</bool>
<bool name="config_show_wifi_mac_address">false</bool>
<bool name="config_disable_uninstall_update">true</bool>

View File

@@ -119,7 +119,8 @@ public class AvailableMediaDeviceGroupControllerTest {
mAvailableMediaDeviceGroupController.onDeviceAdded(mPreference);
assertThat(mPreferenceGroup.isVisible()).isTrue();
assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
.isEqualTo(mPreference);
}
@Test

View File

@@ -100,7 +100,8 @@ public class ConnectedDeviceGroupControllerTest {
mConnectedDeviceGroupController.onDeviceAdded(mPreference);
assertThat(mPreferenceGroup.isVisible()).isTrue();
assertThat(mPreferenceGroup.findPreference(PREFERENCE_KEY_1)).isEqualTo(mPreference);
assertThat((Preference) mPreferenceGroup.findPreference(PREFERENCE_KEY_1))
.isEqualTo(mPreference);
}
@Test

View File

@@ -16,6 +16,9 @@
package com.android.settings.connecteddevice;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
@@ -43,6 +46,17 @@ public class TopLevelConnectedDevicesPreferenceControllerTest {
mController = new TopLevelConnectedDevicesPreferenceController(mContext, "test_key");
}
@Test
public void getAvailibilityStatus_availableByDefault() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
@Config(qualifiers = "mcc999")
public void getAvailabilityStatus_unsupportedWhenSet() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
@Config(shadows = ShadowAdvancedConnectedDeviceController.class)
public void getSummary_shouldCallAdvancedConnectedDeviceController() {

View File

@@ -29,6 +29,7 @@ import android.hardware.usb.UsbPort;
import android.os.Handler;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -122,8 +123,8 @@ public class UsbDetailsPowerRoleControllerTest {
UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
assertThat(mPreference.isEnabled()).isFalse();
assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey()))
.isEqualTo(mPreference);
assertThat((Preference) mScreen.findPreference(
mDetailsPowerRoleController.getPreferenceKey())).isEqualTo(mPreference);
}
@Test
@@ -134,7 +135,8 @@ public class UsbDetailsPowerRoleControllerTest {
mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
UsbPort.DATA_ROLE_DEVICE);
assertThat(mScreen.findPreference(mDetailsPowerRoleController.getPreferenceKey())).isNull();
assertThat((Preference) mScreen.findPreference(
mDetailsPowerRoleController.getPreferenceKey())).isNull();
}
@Test

View File

@@ -71,7 +71,9 @@ public class BasePreferenceControllerSignatureInspector extends CodeInspector {
.that(badClasses.toString())
.isEmpty();
assertWithMessage("Something in the grandfather list is no longer relevant. Please remove")
assertWithMessage("Something in the grandfather list is no longer relevant. Please remove"
+ "it from packages/apps/Settings/tests/robotests/assets/"
+ "grandfather_invalid_base_preference_controller_constructor")
.that(grandfather)
.isEmpty();
}

View File

@@ -105,7 +105,7 @@ public class BuildNumberPreferenceControllerTest {
public void displayPref_shouldAlwaysDisplay() {
mController.displayPreference(mScreen);
verify(mScreen.findPreference(mController.getPreferenceKey()))
verify((Preference) mScreen.findPreference(mController.getPreferenceKey()))
.setSummary(BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY));
verify(mScreen, never()).removePreference(any(Preference.class));
}

View File

@@ -17,12 +17,14 @@
package com.android.settings.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
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.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -40,11 +42,13 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
import org.robolectric.annotation.Config;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class TopLevelDisplayPreferenceControllerTest {
@Mock
private Context mContext;
@Mock
private PackageManager mPackageManager;
@@ -54,6 +58,7 @@ public class TopLevelDisplayPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getString(R.string.config_wallpaper_picker_package)).thenReturn("pkg");
when(mContext.getString(R.string.config_wallpaper_picker_class)).thenReturn("cls");
@@ -62,10 +67,16 @@ public class TopLevelDisplayPreferenceControllerTest {
}
@Test
public void getAvailability_alwaysAvailable() {
public void getAvailibilityStatus_availableByDefault() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
@Config(qualifiers = "mcc999")
public void getAvailabilityStatus_unsupportedWhenSet() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getSummary_hasWallpaper_shouldReturnWallpaperSummary() {
final List<ResolveInfo> resolveInfos = new ArrayList<>();

View File

@@ -16,6 +16,8 @@
package com.android.settings.fuelgauge;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel;
import static com.google.common.truth.Truth.assertThat;
@@ -25,17 +27,30 @@ import android.content.Context;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class TopLevelBatteryPreferenceControllerTest {
private Context mContext;
private TopLevelBatteryPreferenceController mController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new TopLevelBatteryPreferenceController(mContext, "test_key");
}
@Test
public void getAvailibilityStatus_availableByDefault() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE);
}
@Test
@Config(qualifiers = "mcc999")
public void getAvailabilityStatus_unsupportedWhenSet() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test

View File

@@ -1,89 +0,0 @@
/*
* 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.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AutoBatterySaverPreferenceControllerTest {
private AutoBatterySaverPreferenceController mController;
private Context mContext;
private SwitchPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPreference = new SwitchPreference(mContext);
mController = new AutoBatterySaverPreferenceController(mContext);
}
@Test
public void testUpdateState_lowPowerLevelZero_preferenceNotChecked() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isFalse();
}
@Test
public void testUpdateState_lowPowerLevelZero_preferenceChecked() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
mController.updateState(mPreference);
assertThat(mPreference.isChecked()).isTrue();
}
@Test
public void testOnPreferenceChange_turnOn_setValueNotZero() {
mController.onPreferenceChange(mPreference, true);
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isNotEqualTo(0);
}
@Test
public void testOnPreferenceChange_turnOff_setValueZero() {
mController.onPreferenceChange(mPreference, false);
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(0);
}
@Test
public void testIsChecked_useDefaultValue_returnFalse() {
assertThat(mController.isChecked()).isFalse();
}
}

View File

@@ -1,117 +0,0 @@
/*
* 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.fuelgauge.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import androidx.lifecycle.LifecycleOwner;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class AutoBatterySeekBarPreferenceControllerTest {
private static final int TRIGGER_LEVEL = 20;
private static final int INTERVAL = 5;
private AutoBatterySeekBarPreferenceController mController;
private Context mContext;
private SeekBarPreference mPreference;
private Lifecycle mLifecycle;
private LifecycleOwner mLifecycleOwner;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
mContext = RuntimeEnvironment.application;
mPreference = new SeekBarPreference(mContext);
mPreference.setMax(100);
mController = new AutoBatterySeekBarPreferenceController(mContext, mLifecycle);
}
@Test
public void testPreference_lowPowerLevelZero_preferenceInvisible() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isFalse();
}
@Test
public void testPreference_defaultValue_preferenceNotVisible() {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isFalse();
}
@Test
public void testPreference_lowPowerLevelNotZero_updatePreference() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getTitle()).isEqualTo("20%");
assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL / INTERVAL);
}
@Test
public void testOnPreferenceChange_updateValue() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
mController.onPreferenceChange(mPreference, TRIGGER_LEVEL / INTERVAL);
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0)).isEqualTo(TRIGGER_LEVEL);
}
@Test
public void testOnPreferenceChange_changeMax() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 50);
mController.updateState(mPreference);
assertThat(mPreference.getMax()).isEqualTo(50 / INTERVAL);
}
@Test
public void testOnPreferenceChange_noChangeMax() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX, 0);
mController.updateState(mPreference);
assertThat(mPreference.getMax()).isEqualTo(100);
}
}

View File

@@ -0,0 +1,57 @@
package com.android.settings.fuelgauge.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class BatterySaverScheduleRadioButtonsControllerTest {
private Context mContext;
private ContentResolver mResolver;
private BatterySaverScheduleRadioButtonsController mController;
private BatterySaverScheduleSeekBarController mSeekBarController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mSeekBarController = new BatterySaverScheduleSeekBarController(mContext);
mController = new BatterySaverScheduleRadioButtonsController(
mContext, mSeekBarController);
mResolver = mContext.getContentResolver();
}
@Test
public void getDefaultKey_routine_returnsCorrectValue() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_DYNAMIC);
assertThat(mController.getDefaultKey())
.isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_ROUTINE);
}
@Test
public void getDefaultKey_automatic_returnsCorrectValue() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
assertThat(mController.getDefaultKey())
.isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_PERCENTAGE);
}
@Test
public void getDefaultKey_none_returnsCorrectValue() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
assertThat(mController.getDefaultKey())
.isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
}
}

View File

@@ -0,0 +1,65 @@
package com.android.settings.fuelgauge.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class BatterySaverScheduleSeekBarControllerTest {
private Context mContext;
private ContentResolver mResolver;
private BatterySaverScheduleSeekBarController mController;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new BatterySaverScheduleSeekBarController(mContext);
mResolver = mContext.getContentResolver();
}
@Test
public void onPreferenceChange_updatesSettingsGlobal() {
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
mController.onPreferenceChange(mController.mSeekBarPreference, 10);
assertThat(Settings.Global.getInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
.isEqualTo(50);
assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo("50%");
}
@Test
public void updateSeekBar_routineMode_hasCorrectProperties() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_DYNAMIC);
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
}
@Test
public void updateSeekBar_percentageMode_hasCorrectProperties() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
}
@Test
public void updateSeekBar_noneMode_hasCorrectProperties() {
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
}
}

View File

@@ -28,33 +28,27 @@ import android.content.Context;
import android.net.Uri;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.SettingsSliceProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowContentResolver;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@RunWith(RobolectricTestRunner.class)
public class ContextualCardLoaderTest {
private Context mContext;
private ContextualCardLoader mContextualCardLoader;
private SettingsSliceProvider mProvider;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mContextualCardLoader = spy(new ContextualCardLoader(mContext));
mProvider = new SettingsSliceProvider();
ShadowContentResolver.registerProviderInternal(SettingsSliceProvider.SLICE_AUTHORITY,
mProvider);
}
@Test
@@ -210,4 +204,4 @@ public class ContextualCardLoaderTest {
.build());
return cards;
}
}
}

View File

@@ -1,86 +0,0 @@
/*
* 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.homepage.contextualcards.conditional;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.IntentFilter;
import android.os.PowerManager;
import com.android.settings.fuelgauge.BatterySaverReceiver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPowerManager;
@RunWith(RobolectricTestRunner.class)
public class BatterySaverConditionControllerTest {
@Mock
private ConditionManager mConditionManager;
private ShadowPowerManager mPowerManager;
private Context mContext;
private BatterySaverConditionController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mPowerManager = Shadows.shadowOf(mContext.getSystemService(PowerManager.class));
mController = new BatterySaverConditionController(mContext, mConditionManager);
}
@Test
public void startMonitor_shouldRegisterReceiver() {
mController.startMonitoringStateChange();
verify(mContext).registerReceiver(any(BatterySaverReceiver.class), any(IntentFilter.class));
}
@Test
public void stopMonitor_shouldUnregisterReceiver() {
mController.startMonitoringStateChange();
mController.stopMonitoringStateChange();
verify(mContext).unregisterReceiver(any(BatterySaverReceiver.class));
}
@Test
public void isDisplayable_PowerSaverOn_true() {
mPowerManager.setIsPowerSaveMode(true);
assertThat(mController.isDisplayable()).isTrue();
}
@Test
public void isDisplayable_PowerSaverOff_false() {
mPowerManager.setIsPowerSaveMode(false);
assertThat(mController.isDisplayable()).isFalse();
}
}

View File

@@ -0,0 +1,137 @@
/*
* 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.network;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.telephony.SubscriptionManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
public class MultiNetworkHeaderControllerTest {
private static final String KEY_HEADER = "multi_network_header";
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
private SubscriptionsPreferenceController mSubscriptionsController;
@Mock
private SubscriptionManager mSubscriptionManager;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
private MultiNetworkHeaderController mHeaderController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mPreferenceScreen.findPreference(eq(KEY_HEADER))).thenReturn(mPreferenceCategory);
mHeaderController = spy(new MultiNetworkHeaderController(mContext, KEY_HEADER));
doReturn(mSubscriptionsController).when(mHeaderController).createSubscriptionsController(
mLifecycle);
}
@Test
public void isAvailable_beforeInitIsCalled_notAvailable() {
assertThat(mHeaderController.isAvailable()).isFalse();
}
// When calling displayPreference, the header itself should only be visible if the
// subscriptions controller says it is available. This is a helper for test cases of this logic.
private void displayPreferenceTest(boolean subscriptionsAvailable,
boolean setVisibleExpectedValue) {
when(mSubscriptionsController.isAvailable()).thenReturn(subscriptionsAvailable);
mHeaderController.init(mLifecycle);
mHeaderController.displayPreference(mPreferenceScreen);
verify(mPreferenceCategory, never()).setVisible(eq(!setVisibleExpectedValue));
verify(mPreferenceCategory, atLeastOnce()).setVisible(eq(setVisibleExpectedValue));
}
@Test
public void displayPreference_subscriptionsNotAvailable_categoryIsNotVisible() {
displayPreferenceTest(false, false);
}
@Test
public void displayPreference_subscriptionsAvailable_categoryIsVisible() {
displayPreferenceTest(true, true);
}
@Test
public void onChildUpdated_subscriptionsBecameAvailable_categoryIsVisible() {
when(mSubscriptionsController.isAvailable()).thenReturn(false);
mHeaderController.init(mLifecycle);
mHeaderController.displayPreference(mPreferenceScreen);
when(mSubscriptionsController.isAvailable()).thenReturn(true);
mHeaderController.onChildrenUpdated();
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
verify(mPreferenceCategory, atLeastOnce()).setVisible(captor.capture());
List<Boolean> values = captor.getAllValues();
assertThat(values.get(values.size()-1)).isEqualTo(Boolean.TRUE);
}
@Test
public void onChildUpdated_subscriptionsBecameUnavailable_categoryIsNotVisible() {
when(mSubscriptionsController.isAvailable()).thenReturn(true);
mHeaderController.init(mLifecycle);
mHeaderController.displayPreference(mPreferenceScreen);
when(mSubscriptionsController.isAvailable()).thenReturn(false);
mHeaderController.onChildrenUpdated();
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
verify(mPreferenceCategory, atLeastOnce()).setVisible(captor.capture());
List<Boolean> values = captor.getAllValues();
assertThat(values.get(values.size()-1)).isEqualTo(Boolean.FALSE);
}
}

View File

@@ -0,0 +1,218 @@
/*
* 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.network;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
@RunWith(RobolectricTestRunner.class)
public class SubscriptionsPreferenceControllerTest {
private static final String KEY = "preference_group";
@Mock
private PreferenceScreen mScreen;
@Mock
private PreferenceCategory mPreferenceCategory;
@Mock
private SubscriptionManager mSubscriptionManager;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
private SubscriptionsPreferenceController mController;
private int mOnChildUpdatedCount;
private SubscriptionsPreferenceController.UpdateListener mUpdateListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
when(mPreferenceCategory.getContext()).thenReturn(mContext);
mOnChildUpdatedCount = 0;
mUpdateListener = () -> mOnChildUpdatedCount++;
mController = new SubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener,
KEY, 5);
}
@Test
public void isAvailable_oneSubscription_availableFalse() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_twoSubscriptions_availableTrue() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_fiveSubscriptions_availableTrue() {
final ArrayList<SubscriptionInfo> subs = new ArrayList<>();
for (int i = 0; i < 5; i++) {
subs.add(mock(SubscriptionInfo.class));
}
SubscriptionUtil.setAvailableSubscriptionsForTesting(subs);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_airplaneModeOn_availableFalse() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
assertThat(mController.isAvailable()).isTrue();
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isTrue();
final int updateCountBeforeModeChange = mOnChildUpdatedCount;
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
mController.onAirplaneModeChanged(true);
assertThat(mController.isAvailable()).isFalse();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
}
@Test
public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
SubscriptionUtil.setAvailableSubscriptionsForTesting(
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isFalse();
final int updateCountBeforeModeChange = mOnChildUpdatedCount;
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
mController.onAirplaneModeChanged(false);
assertThat(mController.isAvailable()).isTrue();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeModeChange + 1);
}
@Test
public void onSubscriptionsChanged_countBecameTwo_eventFired() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isFalse();
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
}
@Test
public void onSubscriptionsChanged_countBecameOne_eventFired() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onResume();
mController.displayPreference(mScreen);
assertThat(mController.isAvailable()).isTrue();
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isFalse();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
}
@Test
public void onSubscriptionsChanged_subscriptionReplaced_preferencesChanged() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
final SubscriptionInfo sub3 = mock(SubscriptionInfo.class);
when(sub1.getDisplayName()).thenReturn("sub1");
when(sub2.getDisplayName()).thenReturn("sub2");
when(sub3.getDisplayName()).thenReturn("sub3");
when(sub1.getSubscriptionId()).thenReturn(1);
when(sub2.getSubscriptionId()).thenReturn(2);
when(sub3.getSubscriptionId()).thenReturn(3);
// Start out with only sub1 and sub2.
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub2));
mController.onResume();
mController.displayPreference(mScreen);
final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
verify(mPreferenceCategory, times(2)).addPreference(captor.capture());
assertThat(captor.getAllValues().size()).isEqualTo(2);
assertThat(captor.getAllValues().get(0).getTitle()).isEqualTo("sub1");
assertThat(captor.getAllValues().get(1).getTitle()).isEqualTo("sub2");
// Now replace sub2 with sub3, and make sure the old preference was removed and the new
// preference was added.
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(sub1, sub3));
mController.onSubscriptionsChanged();
assertThat(mController.isAvailable()).isTrue();
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
verify(mPreferenceCategory).removePreference(captor.capture());
assertThat(captor.getValue().getTitle()).isEqualTo("sub2");
verify(mPreferenceCategory, times(3)).addPreference(captor.capture());
assertThat(captor.getValue().getTitle()).isEqualTo("sub3");
}
}

View File

@@ -218,7 +218,8 @@ public class WorkSoundPreferenceControllerTest {
mController.displayPreference(mScreen);
mController.onResume();
verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)).setVisible(false);
verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
.setVisible(false);
}
@Test
@@ -242,11 +243,11 @@ public class WorkSoundPreferenceControllerTest {
verify(mWorkCategory, times(2)).setVisible(true);
// Sound preferences should explain that the profile isn't available yet.
verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
verify((Preference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE))
.setSummary(eq(notAvailable));
verify(mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
verify((Preference) mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE))
.setSummary(eq(notAvailable));
verify(mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
verify((Preference) mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE))
.setSummary(eq(notAvailable));
}

View File

@@ -83,12 +83,12 @@ public class ZenModeAutomaticRulesPreferenceControllerTest {
String ruleId2 = "test2_id";
String ruleId3 = "test3_id";
AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30);
rMap.put(ruleId1, autoRule1);
rMap.put(ruleId2, autoRule2);
@@ -109,10 +109,10 @@ public class ZenModeAutomaticRulesPreferenceControllerTest {
String ruleId1 = "test1_id";
String ruleId2 = "test2_id";
AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20);
rMap.put(ruleId1, autoRule1);
rMap.put(ruleId2, autoRule2);
@@ -130,8 +130,8 @@ public class ZenModeAutomaticRulesPreferenceControllerTest {
final int NUM_RULES = 1;
Map<String, AutomaticZenRule> rMap = new HashMap<>();
String testId = "test1_id";
AutomaticZenRule rule = new AutomaticZenRule("rule_name", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
AutomaticZenRule rule = new AutomaticZenRule("rule_name", null, null,
null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10);
rMap.put(testId, rule);
when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES);

View File

@@ -69,13 +69,14 @@ public class ZenModeBackendTest {
for (int i = 0; i < numRules; i++) {
ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true,
i * 2));
}
if (addDefaultRules) {
ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
}
@@ -90,13 +91,14 @@ public class ZenModeBackendTest {
for (int i = 0; i < numRules; i++) {
ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true,
numRules - i));
}
if (addDefaultRules) {
ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null,
ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
}

View File

@@ -23,6 +23,7 @@ import android.content.Context;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
@@ -64,6 +65,7 @@ public class FakeFeatureFactory extends FeatureFactory {
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -108,6 +110,7 @@ public class FakeFeatureFactory extends FeatureFactory {
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
panelFeatureProvider = mock(PanelFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
}
@Override
@@ -195,7 +198,13 @@ public class FakeFeatureFactory extends FeatureFactory {
return panelFeatureProvider;
}
@Override
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
return mContextualCardFeatureProvider;
}
@Override
public FaceFeatureProvider getFaceFeatureProvider() {
return mFaceFeatureProvider;
}
}

View File

@@ -22,9 +22,11 @@ import static org.mockito.Mockito.mock;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.util.Size;
import android.view.SurfaceHolder;
import com.android.settings.R;
@@ -48,7 +50,7 @@ import org.robolectric.RuntimeEnvironment;
public class QrCameraTest {
@Mock
private SurfaceHolder mSurfaceHolder;
private SurfaceTexture mSurfaceTexture;
private QrCamera mCamera;
private Context mContext;
@@ -78,6 +80,11 @@ public class QrCameraTest {
mCameraCallbacked = true;
mCallbackSignal.countDown();
}
@Override
public void setTransform(Matrix transform) {
// Do nothing
}
}
private ScannerTestCallback mScannerCallback;
@@ -87,7 +94,7 @@ public class QrCameraTest {
mContext = RuntimeEnvironment.application;
mScannerCallback = new ScannerTestCallback();
mCamera = new QrCamera(mContext, mScannerCallback);
mSurfaceHolder = mock(SurfaceHolder.class);
mSurfaceTexture = mock(SurfaceTexture.class);
mQrCode = "";
mCameraCallbacked = false;
mCallbackSignal = null;
@@ -96,7 +103,7 @@ public class QrCameraTest {
@Test
public void testCamera_Init_Callback() throws InterruptedException {
mCallbackSignal = new CountDownLatch(1);
mCamera.start(mSurfaceHolder);
mCamera.start(mSurfaceTexture);
mCallbackSignal.await(5000, TimeUnit.MILLISECONDS);
assertThat(mCameraCallbacked).isTrue();
}

View File

@@ -27,7 +27,7 @@ LOCAL_JAVA_LIBRARIES := \
android.test.base
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
androidx.test.rules \
app-helpers-core \
launcher-helper-lib \
metrics-helper-lib \

View File

@@ -31,7 +31,7 @@
<uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES"/>
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings.ui"
android:label="Android Settings Functional UI Tests" />
</manifest>

View File

@@ -24,7 +24,7 @@
<option name="test-tag" value="SettingsUITests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.settings.ui" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>

View File

@@ -24,9 +24,6 @@ import android.app.Instrumentation;
import android.content.Intent;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
@@ -34,6 +31,10 @@ import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.text.TextUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -21,14 +21,15 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.system.helpers.ActivityHelper;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -18,12 +18,13 @@ package com.android.settings.ui;
import android.content.Intent;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.system.helpers.SettingsHelper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.ui.testutils.SettingsTestUtils;
import org.junit.After;

View File

@@ -24,14 +24,15 @@ import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -22,9 +22,6 @@ import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.Direction;
import android.support.test.uiautomator.UiDevice;
@@ -32,6 +29,10 @@ import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.system.helpers.SettingsHelper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.ui.testutils.SettingsTestUtils;
import org.junit.After;

View File

@@ -18,12 +18,13 @@ package com.android.settings.ui;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.system.helpers.SettingsHelper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.ui.testutils.SettingsTestUtils;
import org.junit.After;

View File

@@ -18,12 +18,13 @@ package com.android.settings.ui;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiDevice;
import android.system.helpers.SettingsHelper;
import android.test.suitebuilder.annotation.MediumTest;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.settings.ui.testutils.SettingsTestUtils;
import org.junit.After;

View File

@@ -20,8 +20,6 @@ import android.content.Intent;
import android.os.SystemClock;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
@@ -29,6 +27,9 @@ import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -20,15 +20,16 @@ import static junit.framework.Assert.assertTrue;
import android.os.RemoteException;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.system.helpers.SettingsHelper;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -24,8 +24,6 @@ import android.net.wifi.WifiManager;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.Until;
@@ -34,6 +32,9 @@ import android.system.helpers.SettingsHelper;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -17,6 +17,7 @@ package com.android.settings.ui;
import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -24,9 +25,6 @@ import static org.junit.Assert.assertTrue;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
@@ -39,6 +37,10 @@ import android.support.test.uiautomator.Until;
import android.system.helpers.SettingsHelper;
import android.system.helpers.SettingsHelper.SettingsType;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@@ -21,13 +21,14 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -21,13 +21,14 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -27,12 +27,13 @@ import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.TextUtils;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

View File

@@ -14,10 +14,10 @@ LOCAL_JAVA_LIBRARIES := \
LOCAL_STATIC_JAVA_LIBRARIES := \
android-support-test \
espresso-core \
espresso-contrib-nodep \
espresso-intents-nodep \
androidx.test.rules \
androidx.test.espresso.core \
androidx.test.espresso.contrib-nodeps \
androidx.test.espresso.intents-nodeps \
mockito-target-minus-junit4 \
platform-test-annotations \
truth-prebuilt \

View File

@@ -65,7 +65,7 @@
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings"
android:label="Settings Test Cases">
</instrumentation>

View File

@@ -24,7 +24,7 @@
<option name="test-tag" value="SettingsUnitTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.settings.tests.unit" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>

Some files were not shown because too many files have changed in this diff Show More