diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 202335e70be..8e4d6a45869 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1588,6 +1588,10 @@
android:exported="false"
android:screenOrientation="portrait"/>
+
+
diff --git a/res/drawable/ic_face_enroll_introduction_people.xml b/res/drawable/ic_face_enroll_introduction_people.xml
new file mode 100644
index 00000000000..b452efe14fd
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_people.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_face_enroll_introduction_shield.xml b/res/drawable/ic_face_enroll_introduction_shield.xml
new file mode 100644
index 00000000000..09d3909cbe1
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_shield.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_face_enroll_introduction_visibility.xml b/res/drawable/ic_face_enroll_introduction_visibility.xml
new file mode 100644
index 00000000000..04ff21f4cac
--- /dev/null
+++ b/res/drawable/ic_face_enroll_introduction_visibility.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/face_enroll_education.xml b/res/layout/face_enroll_education.xml
new file mode 100644
index 00000000000..c41c724cf3c
--- /dev/null
+++ b/res/layout/face_enroll_education.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 3115bb4ca2f..535a531ba9f 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -1,6 +1,6 @@
- #82000000
- @android:color/black
- #783BE5
- #3F5FBD
-
- #cc000000
- @*android:color/material_grey_900
- @*android:color/material_grey_900
- @*android:color/material_grey_800
-
- @*android:color/material_grey_800
- @*android:color/material_grey_800
- #AECBFA
- #5F6368
+ #82000000
+ @android:color/black
+ #783BE5
+ #3F5FBD
+ @*android:color/material_grey_900
+ @*android:color/material_grey_900
+ @*android:color/material_grey_800
+
+ @*android:color/material_grey_800
+ @*android:color/material_grey_800
+ #AECBFA
+ #5F6368
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 42fa3f97fe7..4a4c896a770 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -23,7 +23,9 @@
#20ffffff
@android:color/holo_blue_light
- @color/lock_pattern_view_regular_color
+
+ @color/lock_pattern_view_regular_color
+
#ff84ffff
@color/sud_color_accent_light
#fff44336
@@ -133,9 +135,6 @@
@*android:color/accent_device_default_light
-
- #ccFFFFFF
-
#ffdadce0
#ff1a73e8
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a348f8ad4fc..09ab682cde9 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -409,5 +409,5 @@
80dp
- 360dp
+ 480dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a31de98fb42..e4362eca58e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -888,6 +888,12 @@
Tap to set up face authentication
Face authentication
+
+ How to set up Face unlock
+
+ Use your face to authenticate
+
+
Use accessibility setup
@@ -908,8 +914,12 @@
Use your face to unlock your phone or approve purchases.\n\nNote: You can\u2019t use your face to unlock this device. For more information, contact your organization\u2019s admin.
Use your face to unlock your phone, authorize purchases, or sign in to apps
-
-
+
+
+
+
+
+
Center your face in the circle
@@ -2895,7 +2905,7 @@
Choose wallpaper from
Customize your Pixel
-
+
Try different styles, wallpapers, clocks, and more
Screen saver
@@ -7264,6 +7274,8 @@
work challenge, work, profile
work profile, managed profile, unify, unification, work, profile
gestures
+
+ global actions
pay, tap, payments
backup, back up
gesture
@@ -10148,6 +10160,15 @@
To check time, notifications, and other info, tap your screen.
+
+ To show the global actions panel, press & hold Power button
+
+ Show global actions
+
+ Global actions
+
+ The global actions panel can be accessed even when the device is locked.
+
Swipe fingerprint for notifications
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 951bb048960..4edd943a224 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -197,9 +197,8 @@
- @*android:color/primary_dark_device_default_settings_light
- true
- @*android:color/ripple_material_light
- - @android:color/white
+ - @android:color/transparent
- @android:color/white
- - true
diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml
index 8515bd71892..5dcb1b02d01 100644
--- a/res/xml/gestures.xml
+++ b/res/xml/gestures.xml
@@ -75,4 +75,10 @@
android:fragment="com.android.settings.gestures.PreventRingingGestureSettings"
settings:controller="com.android.settings.gestures.PreventRingingParentPreferenceController" />
+
+
diff --git a/res/xml/global_actions_panel_settings.xml b/res/xml/global_actions_panel_settings.xml
new file mode 100644
index 00000000000..af155bc74fc
--- /dev/null
+++ b/res/xml/global_actions_panel_settings.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/com/android/settings/applications/ApplicationFeatureProvider.java b/src/com/android/settings/applications/ApplicationFeatureProvider.java
index 3ffacb0bc16..e9f877e79bf 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProvider.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProvider.java
@@ -81,6 +81,14 @@ public interface ApplicationFeatureProvider {
*/
Set getKeepEnabledPackages();
+ /**
+ * Returns a user readable text explaining how much time user has spent in an app at a
+ * pre-specified duration.
+ */
+ default CharSequence getTimeSpentInApp(String packageName) {
+ return null;
+ }
+
/**
* Callback that receives the number of packages installed on the device.
*/
diff --git a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
index 7027239f52e..1fd79971c80 100644
--- a/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
+++ b/src/com/android/settings/applications/ApplicationFeatureProviderImpl.java
@@ -41,7 +41,7 @@ import java.util.Set;
public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
- private final Context mContext;
+ protected final Context mContext;
private final PackageManager mPm;
private final IPackageManager mPms;
private final DevicePolicyManager mDpm;
diff --git a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
index 70ffcb3f8e5..b1bbd06e9d6 100644
--- a/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceController.java
@@ -28,7 +28,9 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
import java.util.List;
@@ -38,13 +40,15 @@ public class TimeSpentInAppPreferenceController extends BasePreferenceController
static final Intent SEE_TIME_IN_APP_TEMPLATE = new Intent(Settings.ACTION_APP_USAGE_SETTINGS);
private final PackageManager mPackageManager;
-
+ private final ApplicationFeatureProvider mAppFeatureProvider;
private Intent mIntent;
private String mPackageName;
public TimeSpentInAppPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
mPackageManager = context.getPackageManager();
+ mAppFeatureProvider = FeatureFactory.getFactory(context)
+ .getApplicationFeatureProvider(context);
}
public void setPackageName(String packageName) {
@@ -80,6 +84,11 @@ public class TimeSpentInAppPreferenceController extends BasePreferenceController
}
}
+ @Override
+ public CharSequence getSummary() {
+ return mAppFeatureProvider.getTimeSpentInApp(mPackageName);
+ }
+
private boolean isSystemApp(ResolveInfo info) {
return info != null
&& info.activityInfo != null
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
new file mode 100644
index 00000000000..9660f3b8575
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -0,0 +1,175 @@
+/*
+ * 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 static android.provider.Settings.Secure.FACE_UNLOCK_EDUCATION_INFO_DISPLAYED;
+import static android.security.KeyStore.getApplicationContext;
+
+import android.app.settings.SettingsEnums;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.face.FaceManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CompoundButton;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricEnrollBase;
+import com.android.settings.password.ChooseLockSettingsHelper;
+
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
+import com.google.android.setupdesign.view.IllustrationVideoView;
+
+public class FaceEnrollEducation extends BiometricEnrollBase {
+
+ private static final String TAG = "FaceEducation";
+ private static final int ON = 1;
+ private static final int OFF = 0;
+ // 10 seconds.
+ private static final long FACE_ENROLL_EDUCATION_DELAY = 16000;
+
+ private FaceManager mFaceManager;
+ private FaceEnrollAccessibilityToggle mSwitchDiversity;
+
+ private IllustrationVideoView mIllustrationNormal;
+ private View mIllustrationAccessibility;
+ private Handler mHandler;
+
+ private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
+ new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ mIllustrationNormal.stop();
+ mIllustrationNormal.setVisibility(View.INVISIBLE);
+ mIllustrationAccessibility.setVisibility(View.VISIBLE);
+ } else {
+ mIllustrationNormal.setVisibility(View.VISIBLE);
+ mIllustrationNormal.start();
+ mIllustrationAccessibility.setVisibility(View.INVISIBLE);
+ }
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.face_enroll_education);
+ getLayout().setHeaderText(R.string.security_settings_face_enroll_education_title);
+ setTitle(R.string.security_settings_face_enroll_education_title);
+ mHandler = new Handler();
+
+ mFaceManager = Utils.getFaceManagerOrNull(this);
+ final Button accessibilityButton = findViewById(R.id.accessibility_button);
+ accessibilityButton.setOnClickListener(view -> {
+ mSwitchDiversity.setChecked(true);
+ accessibilityButton.setVisibility(View.GONE);
+ mSwitchDiversity.setVisibility(View.VISIBLE);
+ });
+
+ mSwitchDiversity = findViewById(R.id.toggle_diversity);
+ mSwitchDiversity.setListener(mSwitchDiversityListener);
+
+ mIllustrationNormal = findViewById(R.id.illustration_normal);
+ mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
+
+ mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
+ mFooterBarMixin.setSecondaryButton(
+ new FooterButton.Builder(this)
+ .setText(R.string.security_settings_face_enroll_enrolling_skip)
+ .setListener(this::onSkipButtonClick)
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build()
+ );
+
+ final FooterButton footerButton = new FooterButton.Builder(this)
+ .setText(R.string.wizard_next)
+ .setListener(this::onNextButtonClick)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build();
+
+ mFooterBarMixin.setPrimaryButton(footerButton);
+ final Context context = getApplicationContext();
+ final boolean didDisplayEdu = Settings.Secure.getIntForUser(context.getContentResolver(),
+ FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, OFF, mUserId) == ON;
+ if (!didDisplayEdu) {
+ Settings.Secure.putIntForUser(context.getContentResolver(),
+ FACE_UNLOCK_EDUCATION_INFO_DISPLAYED, ON, mUserId);
+ footerButton.setEnabled(false);
+ mHandler.postDelayed(() -> {
+ footerButton.setEnabled(true);
+ }, FACE_ENROLL_EDUCATION_DELAY);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
+ mSwitchDiversity.isChecked());
+ }
+
+ @Override
+ protected void onNextButtonClick(View view) {
+ final Intent intent = new Intent();
+ if (mToken != null) {
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
+ }
+ if (mUserId != UserHandle.USER_NULL) {
+ intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
+ }
+ final String flattenedString = getString(R.string.config_face_enroll);
+ if (!TextUtils.isEmpty(flattenedString)) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
+ intent.setComponent(componentName);
+ } else {
+ intent.setClass(this, FaceEnrollEnrolling.class);
+ }
+ intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+ WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
+ startActivityForResult(intent, BIOMETRIC_FIND_SENSOR_REQUEST);
+ }
+
+ protected void onSkipButtonClick(View view) {
+ setResult(RESULT_SKIP);
+ finish();
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
+ setResult(resultCode);
+ finish();
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.FACE_ENROLL_INTRO;
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 6887d51e598..525c1a3ee42 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -18,14 +18,9 @@ package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.os.Bundle;
-import android.text.TextUtils;
-import android.view.View;
-import android.widget.Button;
-import android.widget.CompoundButton;
import android.widget.TextView;
import com.android.settings.R;
@@ -38,51 +33,18 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.span.LinkSpan;
-import com.google.android.setupdesign.view.IllustrationVideoView;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceIntro";
private FaceManager mFaceManager;
- private FaceEnrollAccessibilityToggle mSwitchDiversity;
-
- private IllustrationVideoView mIllustrationNormal;
- private View mIllustrationAccessibility;
-
- private CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
- new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (isChecked) {
- mIllustrationNormal.stop();
- mIllustrationNormal.setVisibility(View.INVISIBLE);
- mIllustrationAccessibility.setVisibility(View.VISIBLE);
- } else {
- mIllustrationNormal.setVisibility(View.VISIBLE);
- mIllustrationNormal.start();
- mIllustrationAccessibility.setVisibility(View.INVISIBLE);
- }
- }
- };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFaceManager = Utils.getFaceManagerOrNull(this);
- final Button accessibilityButton = findViewById(R.id.accessibility_button);
- accessibilityButton.setOnClickListener(view -> {
- mSwitchDiversity.setChecked(true);
- accessibilityButton.setVisibility(View.GONE);
- mSwitchDiversity.setVisibility(View.VISIBLE);
- });
-
- mSwitchDiversity = findViewById(R.id.toggle_diversity);
- mSwitchDiversity.setListener(mSwitchDiversityListener);
-
- mIllustrationNormal = findViewById(R.id.illustration_normal);
- mIllustrationAccessibility = findViewById(R.id.illustration_accessibility);
mFooterBarMixin = getLayout().getMixin(FooterBarMixin.class);
if (WizardManagerHelper.isAnySetupWizard(getIntent())) {
@@ -115,13 +77,6 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
);
}
- @Override
- protected void onResume() {
- super.onResume();
- mSwitchDiversityListener.onCheckedChanged(mSwitchDiversity.getSwitch(),
- mSwitchDiversity.isChecked());
- }
-
@Override
protected boolean isDisabledByAdmin() {
return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
@@ -200,16 +155,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected Intent getEnrollingIntent() {
- final String flattenedString = getString(R.string.config_face_enroll);
- final Intent intent = new Intent();
- if (!TextUtils.isEmpty(flattenedString)) {
- ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
- intent.setComponent(componentName);
-
- } else {
- intent.setClass(this, FaceEnrollEnrolling.class);
- }
- intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
+ Intent intent = new Intent(this, FaceEnrollEducation.class);
WizardManagerHelper.copyWizardManagerExtras(getIntent(), intent);
return intent;
}
diff --git a/src/com/android/settings/core/SettingsUIDeviceConfig.java b/src/com/android/settings/core/SettingsUIDeviceConfig.java
index b7aa281408d..8c85c82340c 100644
--- a/src/com/android/settings/core/SettingsUIDeviceConfig.java
+++ b/src/com/android/settings/core/SettingsUIDeviceConfig.java
@@ -33,4 +33,9 @@ public class SettingsUIDeviceConfig {
* {@code true} if near by device suggestion is enabled in connected device page
*/
public static final String BT_NEAR_BY_SUGGESTION_ENABLED = "bt_near_by_suggestion_enabled";
+
+ /**
+ * {@code true} whether or not event_log for generic actions is enabled. Default is true.
+ */
+ public static final String GENERIC_EVENT_LOGGING_ENABLED = "event_logging_enabled";
}
diff --git a/src/com/android/settings/core/instrumentation/SettingsEventLogWriter.java b/src/com/android/settings/core/instrumentation/SettingsEventLogWriter.java
new file mode 100644
index 00000000000..a58555fe11f
--- /dev/null
+++ b/src/com/android/settings/core/instrumentation/SettingsEventLogWriter.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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.core.instrumentation;
+
+import android.content.Context;
+import android.provider.DeviceConfig;
+
+import com.android.settings.core.SettingsUIDeviceConfig;
+import com.android.settingslib.core.instrumentation.EventLogWriter;
+
+public class SettingsEventLogWriter extends EventLogWriter {
+
+ @Override
+ public void visible(Context context, int source, int category) {
+ if (shouldDisableGenericEventLogging()) {
+ return;
+ }
+ super.visible(context, source, category);
+ }
+
+ @Override
+ public void hidden(Context context, int category) {
+ if (shouldDisableGenericEventLogging()) {
+ return;
+ }
+ super.hidden(context, category);
+ }
+
+ @Override
+ public void action(Context context, int category, String pkg) {
+ if (shouldDisableGenericEventLogging()) {
+ return;
+ }
+ super.action(context, category, pkg);
+ }
+
+ @Override
+ public void action(Context context, int category, int value) {
+ if (shouldDisableGenericEventLogging()) {
+ return;
+ }
+ super.action(context, category, value);
+ }
+
+ @Override
+ public void action(Context context, int category, boolean value) {
+ if (shouldDisableGenericEventLogging()) {
+ return;
+ }
+ super.action(context, category, value);
+ }
+
+ private static boolean shouldDisableGenericEventLogging() {
+ return !DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, true /* default */);
+ }
+}
diff --git a/src/com/android/settings/core/instrumentation/SettingsMetricsFeatureProvider.java b/src/com/android/settings/core/instrumentation/SettingsMetricsFeatureProvider.java
index ec057572053..01927fd2d53 100644
--- a/src/com/android/settings/core/instrumentation/SettingsMetricsFeatureProvider.java
+++ b/src/com/android/settings/core/instrumentation/SettingsMetricsFeatureProvider.java
@@ -17,14 +17,29 @@
package com.android.settings.core.instrumentation;
import android.content.Context;
+import android.util.Log;
+import android.util.Pair;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
public class SettingsMetricsFeatureProvider extends MetricsFeatureProvider {
+ private static final String TAG = "SettingsMetricsFeature";
+
@Override
protected void installLogWriters() {
- super.installLogWriters();
mLoggerWriters.add(new StatsLogWriter());
+ mLoggerWriters.add(new SettingsEventLogWriter());
mLoggerWriters.add(new SettingsIntelligenceLogWriter());
}
+
+ /**
+ * @deprecated Use {@link #action(int, int, int, String, int)} instead.
+ */
+ @Deprecated
+ @Override
+ public void action(Context context, int category, Pair... taggedData) {
+ Log.w(TAG, "action(Pair... taggedData) is deprecated, "
+ + "Use action(int, int, int, String, int) instead.");
+ super.action(context, category, taggedData);
+ }
}
diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java
index 283c84f6ec7..68657a48f8e 100644
--- a/src/com/android/settings/datausage/DataUsageUtils.java
+++ b/src/com/android/settings/datausage/DataUsageUtils.java
@@ -178,9 +178,10 @@ public final class DataUsageUtils {
* Returns the default network template based on the availability of mobile data, Wifi. Returns
* ethernet template if both mobile data and Wifi are not available.
*/
- static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
+ public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
if (hasMobileData(context) && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- TelephonyManager telephonyManager = TelephonyManager.from(context);
+ TelephonyManager telephonyManager = TelephonyManager.from(context)
+ .createForSubscriptionId(defaultSubId);
NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
telephonyManager.getSubscriberId(defaultSubId));
return NetworkTemplate.normalize(mobileAll,
diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java
index 38733891901..92afa56cc0a 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardBase.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java
@@ -187,6 +187,14 @@ public abstract class StorageWizardBase extends FragmentActivity {
mNext.setVisibility(View.VISIBLE);
}
+ protected void setBackButtonVisibility(int visible) {
+ mBack.setVisibility(visible);
+ }
+
+ protected void setNextButtonVisibility(int visible) {
+ mNext.setVisibility(visible);
+ }
+
protected void setIcon(int resId) {
final GlifLayout layout = getGlifLayout();
final Drawable icon = getDrawable(resId).mutate();
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
index 1e8c1691bc2..88968b3bd2a 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
@@ -30,6 +30,7 @@ import android.os.SystemProperties;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.util.Log;
+import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -59,7 +60,8 @@ public class StorageWizardFormatProgress extends StorageWizardBase {
setHeaderText(R.string.storage_wizard_format_progress_title, getDiskShortDescription());
setBodyText(R.string.storage_wizard_format_progress_body, getDiskDescription());
-
+ setBackButtonVisibility(View.INVISIBLE);
+ setNextButtonVisibility(View.INVISIBLE);
mTask = (PartitionTask) getLastCustomNonConfigurationInstance();
if (mTask == null) {
mTask = new PartitionTask();
diff --git a/src/com/android/settings/deviceinfo/StorageWizardInit.java b/src/com/android/settings/deviceinfo/StorageWizardInit.java
index 4f9c5e7aba0..426395c24fe 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardInit.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardInit.java
@@ -51,7 +51,7 @@ public class StorageWizardInit extends StorageWizardBase {
mInternal = requireViewById(R.id.storage_wizard_init_internal);
setBackButtonText(R.string.storage_wizard_init_v2_later);
-
+ setNextButtonVisibility(View.INVISIBLE);
if (!mDisk.isAdoptable()) {
// If not adoptable, we only have one choice
mInternal.setEnabled(false);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
index 60f3cb5d4cb..b6f2a8d2fa4 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateProgress.java
@@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.storage.DiskInfo;
import android.util.Log;
+import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -51,7 +52,8 @@ public class StorageWizardMigrateProgress extends StorageWizardBase {
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_migrate_progress_v2_title);
setAuxChecklist();
-
+ setBackButtonVisibility(View.INVISIBLE);
+ setNextButtonVisibility(View.INVISIBLE);
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());
mCallback.onStatusChanged(mMoveId, getPackageManager().getMoveStatus(mMoveId), -1);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
index 10b78af0d7a..8dc878e24af 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveConfirm.java
@@ -73,6 +73,7 @@ public class StorageWizardMoveConfirm extends StorageWizardBase {
setBodyText(R.string.storage_wizard_move_confirm_body, appName, volumeName);
setNextButtonText(R.string.move_app);
+ setBackButtonVisibility(View.INVISIBLE);
}
@Override
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
index 27fa9beb532..1966c9534ae 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMoveProgress.java
@@ -26,6 +26,7 @@ import android.content.pm.PackageManager.MoveCallback;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
+import android.view.View;
import android.widget.Toast;
import com.android.settings.R;
@@ -49,7 +50,8 @@ public class StorageWizardMoveProgress extends StorageWizardBase {
setIcon(R.drawable.ic_swap_horiz);
setHeaderText(R.string.storage_wizard_move_progress_title, appName);
setBodyText(R.string.storage_wizard_move_progress_body, volumeName, appName);
-
+ setBackButtonVisibility(View.INVISIBLE);
+ setNextButtonVisibility(View.INVISIBLE);
// Register for updates and push through current status
getPackageManager().registerMoveCallback(mCallback, new Handler());
mCallback.onStatusChanged(mMoveId, getPackageManager().getMoveStatus(mMoveId), -1);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardReady.java b/src/com/android/settings/deviceinfo/StorageWizardReady.java
index fdb8d8a4938..813bcc6e201 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardReady.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardReady.java
@@ -50,6 +50,7 @@ public class StorageWizardReady extends StorageWizardBase {
}
setNextButtonText(R.string.done);
+ setBackButtonVisibility(View.INVISIBLE);
}
@Override
diff --git a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
index 6aa71873c4d..fab3efad39e 100644
--- a/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
+++ b/src/com/android/settings/display/AdaptiveSleepPreferenceController.java
@@ -20,9 +20,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
@@ -60,10 +57,12 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
- return mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_adaptive_sleep_available)
- ? AVAILABLE
- : UNSUPPORTED_ON_DEVICE;
+ final boolean supportedOnDevice = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_adaptive_sleep_available);
+ if (!supportedOnDevice) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ return hasSufficientPermissions ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
}
@Override
@@ -77,15 +76,4 @@ public class AdaptiveSleepPreferenceController extends TogglePreferenceControlle
? R.string.adaptive_sleep_summary_on
: R.string.adaptive_sleep_summary_off);
}
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- final Preference preference = screen.findPreference(SYSTEM_KEY);
-
- if (preference != null) {
- preference.setEnabled(hasSufficientPermissions);
- }
-
- }
}
diff --git a/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java b/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
index dc569aaa1da..6fc0b0e10e4 100644
--- a/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
+++ b/src/com/android/settings/display/DisplayWhiteBalancePreferenceController.java
@@ -13,17 +13,34 @@
*/
package com.android.settings.display;
+import android.app.ActivityManager;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings.Secure;
+import android.provider.Settings.System;
import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+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.settings.core.TogglePreferenceController;
-public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController {
+public class DisplayWhiteBalancePreferenceController extends TogglePreferenceController
+ implements LifecycleObserver, OnStart, OnStop {
private ColorDisplayManager mColorDisplayManager;
+ @VisibleForTesting
+ ContentObserver mContentObserver;
+ private Preference mPreference;
public DisplayWhiteBalancePreferenceController(Context context, String key) {
super(context, key);
@@ -31,12 +48,8 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
@Override
public int getAvailabilityStatus() {
- // Display white balance is only valid in linear light space. COLOR_MODE_SATURATED implies
- // unmanaged color mode, and hence unknown color processing conditions.
- return ColorDisplayManager.isDisplayWhiteBalanceAvailable(mContext) &&
- getColorDisplayManager().getColorMode() !=
- ColorDisplayManager.COLOR_MODE_SATURATED ?
- AVAILABLE : DISABLED_FOR_USER;
+ return getColorDisplayManager().isDisplayWhiteBalanceAvailable(mContext) ?
+ AVAILABLE : DISABLED_FOR_USER;
}
@Override
@@ -49,6 +62,50 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
return getColorDisplayManager().setDisplayWhiteBalanceEnabled(isChecked);
}
+ @Override
+ public void onStart() {
+ if (!isAvailable()) {
+ return;
+ }
+
+ final ContentResolver cr = mContext.getContentResolver();
+ mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateVisibility();
+ }
+ };
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+ cr.registerContentObserver(
+ Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+ cr.registerContentObserver(
+ System.getUriFor(System.DISPLAY_COLOR_MODE),
+ false /* notifyForDescendants */, mContentObserver,
+ ActivityManager.getCurrentUser());
+
+ updateVisibility();
+ }
+
+ @Override
+ public void onStop() {
+ if (mContentObserver != null) {
+ mContext.getContentResolver().unregisterContentObserver(mContentObserver);
+ mContentObserver = null;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ }
+
@VisibleForTesting
ColorDisplayManager getColorDisplayManager() {
if (mColorDisplayManager == null) {
@@ -56,4 +113,17 @@ public class DisplayWhiteBalancePreferenceController extends TogglePreferenceCon
}
return mColorDisplayManager;
}
+
+ @VisibleForTesting
+ void updateVisibility() {
+ if (mPreference != null) {
+ ColorDisplayManager cdm = getColorDisplayManager();
+
+ // Display white balance is only valid in linear light space. COLOR_MODE_SATURATED
+ // implies unmanaged color mode, and hence unknown color processing conditions.
+ // We also disallow display white balance when color accessibility features are enabled.
+ mPreference.setVisible(cdm.getColorMode() != ColorDisplayManager.COLOR_MODE_SATURATED &&
+ !cdm.areAccessibilityTransformsEnabled(mContext));
+ }
+ }
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 85a08793b42..880255b212c 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -378,6 +378,9 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
@VisibleForTesting
void restartBatteryInfoLoader() {
+ if (getContext() == null) {
+ return;
+ }
getLoaderManager().restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
mBatteryInfoLoaderCallbacks);
if (mPowerFeatureProvider.isEstimateDebugEnabled()) {
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
index a936e99f751..5442e7d02c8 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarController.java
@@ -99,10 +99,15 @@ public class BatterySaverScheduleSeekBarController implements
}
}
+ /**
+ * Adds the seekbar to the end of the provided preference screen
+ *
+ * @param screen The preference screen to add the seekbar to
+ */
public void addToScreen(PreferenceScreen screen) {
// makes sure it gets added after the preferences if called due to first time battery
// saver message
- mSeekBarPreference.setOrder(5);
+ mSeekBarPreference.setOrder(100);
screen.addPreference(mSeekBarPreference);
}
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
index 6553c609a1b..31ee278eafa 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java
@@ -64,6 +64,7 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
final ContentObserver mSettingsObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
+ getPreferenceScreen().removeAll();
updateCandidates();
}
};
diff --git a/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java b/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java
new file mode 100644
index 00000000000..b980499ef90
--- /dev/null
+++ b/src/com/android/settings/gestures/GlobalActionsPanelPreferenceController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 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.gestures;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+public class GlobalActionsPanelPreferenceController extends GesturePreferenceController {
+ private static final String PREF_KEY_VIDEO = "global_actions_panel_video";
+
+ @VisibleForTesting
+ protected static final String ENABLED_SETTING = Settings.Secure.GLOBAL_ACTIONS_PANEL_ENABLED;
+ @VisibleForTesting
+ protected static final String AVAILABLE_SETTING =
+ Settings.Secure.GLOBAL_ACTIONS_PANEL_AVAILABLE;
+
+ @VisibleForTesting
+ protected static final String TOGGLE_KEY = "gesture_global_actions_panel_switch";
+
+ public GlobalActionsPanelPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ int enabled = Settings.Secure.getInt(mContext.getContentResolver(), AVAILABLE_SETTING, 0);
+ return enabled == 1 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putInt(mContext.getContentResolver(), ENABLED_SETTING,
+ isChecked ? 1 : 0);
+ }
+
+ @Override
+ protected String getVideoPrefKey() {
+ return PREF_KEY_VIDEO;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return TextUtils.equals(getPreferenceKey(), TOGGLE_KEY);
+ }
+
+ @Override
+ public boolean isChecked() {
+ int enabled = Settings.Secure.getInt(mContext.getContentResolver(), ENABLED_SETTING, 0);
+ return enabled == 1;
+ }
+}
diff --git a/src/com/android/settings/gestures/GlobalActionsPanelSettings.java b/src/com/android/settings/gestures/GlobalActionsPanelSettings.java
new file mode 100644
index 00000000000..fe9a9e80cba
--- /dev/null
+++ b/src/com/android/settings/gestures/GlobalActionsPanelSettings.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 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.gestures;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class GlobalActionsPanelSettings extends DashboardFragment {
+
+ private static final String TAG = "GlobalActionsPanelSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.GLOBAL_ACTIONS_PANEL_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.global_actions_panel_settings;
+ }
+
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.global_actions_panel_settings;
+ return Arrays.asList(sir);
+ }
+ };
+}
diff --git a/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java b/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java
index 337ad2ea2a3..0c5adc4af7b 100644
--- a/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceController.java
@@ -39,7 +39,7 @@ public class SystemNavigationEdgeToEdgePreferenceController extends
@VisibleForTesting
public SystemNavigationEdgeToEdgePreferenceController(Context context,
IOverlayManager overlayManager, String key) {
- super(context, overlayManager, key);
+ super(context, overlayManager, key, NAV_BAR_MODE_GESTURAL_OVERLAY);
}
@Override
diff --git a/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java
index 728c5df0342..7ac9a037477 100644
--- a/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceController.java
@@ -39,7 +39,7 @@ public class SystemNavigationLegacyPreferenceController extends
@VisibleForTesting
public SystemNavigationLegacyPreferenceController(Context context,
IOverlayManager overlayManager, String key) {
- super(context, overlayManager, key);
+ super(context, overlayManager, key, NAV_BAR_MODE_3BUTTON_OVERLAY);
}
@Override
diff --git a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
index f2c8252be39..664e7bb2b42 100644
--- a/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationPreferenceController.java
@@ -52,16 +52,18 @@ public abstract class SystemNavigationPreferenceController extends GesturePrefer
protected final IOverlayManager mOverlayManager;
protected PreferenceScreen mPreferenceScreen;
+ private final String mOverlayPackage;
public SystemNavigationPreferenceController(Context context, IOverlayManager overlayManager,
- String key) {
+ String key, String overlayPackage) {
super(context, key);
mOverlayManager = overlayManager;
+ mOverlayPackage = overlayPackage;
}
@Override
public int getAvailabilityStatus() {
- return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return isGestureAvailable(mContext, mOverlayPackage) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
@@ -105,23 +107,43 @@ public abstract class SystemNavigationPreferenceController extends GesturePrefer
return PREF_KEY_VIDEO;
}
+
static boolean isGestureAvailable(Context context) {
+ return isGestureAvailable(context, null /* overlayPackage */);
+ }
+
+ static boolean isGestureAvailable(Context context, String overlayPackage) {
+ // Skip if the swipe up settings are not available
if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
return false;
}
+ // Skip if the recents component is not defined
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
if (recentsComponentName == null) {
return false;
}
+
+ // Skip if the overview proxy service exists
+ final PackageManager pm = context.getPackageManager();
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
- if (context.getPackageManager().resolveService(quickStepIntent,
- PackageManager.MATCH_SYSTEM_ONLY) == null) {
+ if (pm.resolveService(quickStepIntent, PackageManager.MATCH_SYSTEM_ONLY) == null) {
return false;
}
+
+ // Skip if the required overlay package is defined but doesn't exist
+ if (overlayPackage != null) {
+ try {
+ return pm.getPackageInfo(overlayPackage, 0 /* flags */) != null;
+ } catch (PackageManager.NameNotFoundException e) {
+ // Not found, just return unavailable
+ return false;
+ }
+ }
+
return true;
}
diff --git a/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java b/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java
index cf2886f88a6..592b2311e44 100644
--- a/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java
+++ b/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceController.java
@@ -39,7 +39,7 @@ public class SystemNavigationSwipeUpPreferenceController extends
@VisibleForTesting
public SystemNavigationSwipeUpPreferenceController(Context context,
IOverlayManager overlayManager, String key) {
- super(context, overlayManager, key);
+ super(context, overlayManager, key, NAV_BAR_MODE_2BUTTON_OVERLAY);
}
@Override
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 6d16d7f56cb..e7676649f3f 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -42,8 +42,11 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- updateWindowProperties();
setContentView(R.layout.settings_homepage_container);
+ final View root = findViewById(R.id.settings_homepage_container);
+ root.setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+
setHomepageContainerPaddingTop();
final Toolbar toolbar = findViewById(R.id.search_action_bar);
@@ -76,29 +79,15 @@ public class SettingsHomepageActivity extends SettingsBaseActivity {
fragmentTransaction.commit();
}
- private void updateWindowProperties() {
- final View decorView = getWindow().getDecorView();
- decorView.setSystemUiVisibility(
- decorView.getSystemUiVisibility() |
- View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- );
-
- getWindow().setStatusBarColor(getColor(R.color.homepage_status_bar_color));
- }
-
@VisibleForTesting
void setHomepageContainerPaddingTop() {
final View view = this.findViewById(R.id.homepage_container);
- final int statusBarHeight = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
final int searchBarHeight = getResources().getDimensionPixelSize(R.dimen.search_bar_height);
final int searchBarMargin = getResources().getDimensionPixelSize(R.dimen.search_bar_margin);
- // The top padding is the height of status bar + height of action bar(48dp) + top/bottom
- // margins(16dp)
- final int paddingTop = statusBarHeight + searchBarHeight + searchBarMargin * 2;
+ // The top padding is the height of action bar(48dp) + top/bottom margins(16dp)
+ final int paddingTop = searchBarHeight + searchBarMargin * 2;
view.setPadding(0 /* left */, paddingTop, 0 /* right */, 0 /* bottom */);
}
}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index f9753484180..b83a712bc54 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -112,8 +112,10 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
final View swipeBackground = holder.itemView.findViewById(R.id.dismissal_swipe_background);
sliceLiveData.removeObservers(mLifecycleOwner);
- // set the background to Gone in case the holder is reused.
- swipeBackground.setVisibility(View.GONE);
+ // set the background to GONE in case the holder is reused.
+ if (swipeBackground != null) {
+ swipeBackground.setVisibility(View.GONE);
+ }
sliceLiveData.observe(mLifecycleOwner, slice -> {
if (slice == null) {
Log.w(TAG, "Slice is null");
@@ -140,8 +142,9 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, Life
default:
mFullCardHelper.bindView(holder, card, slice);
}
-
- swipeBackground.setVisibility(View.VISIBLE);
+ if (swipeBackground != null) {
+ swipeBackground.setVisibility(View.VISIBLE);
+ }
});
switch (holder.getItemViewType()) {
diff --git a/src/com/android/settings/network/MobileDataEnabledListener.java b/src/com/android/settings/network/MobileDataEnabledListener.java
new file mode 100644
index 00000000000..8344f886f7f
--- /dev/null
+++ b/src/com/android/settings/network/MobileDataEnabledListener.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 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 android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+
+/** Helper class to listen for changes in the enabled state of mobile data. */
+public class MobileDataEnabledListener extends ContentObserver {
+ private Context mContext;
+ private Client mClient;
+ private int mSubId;
+
+ public interface Client {
+ void onMobileDataEnabledChange();
+ }
+
+ public MobileDataEnabledListener(Context context, Client client) {
+ super(new Handler());
+ mContext = context;
+ mClient = client;
+ mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ /** Starts listening to changes in the enabled state for data on the given subscription id. */
+ public void start(int subId) {
+ mSubId = subId;
+ Uri uri;
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
+ } else {
+ uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + mSubId);
+ }
+ mContext.getContentResolver().registerContentObserver(uri, true /*notifyForDescendants*/,
+ this);
+ }
+
+ public int getSubId() {
+ return mSubId;
+ }
+
+ public MobileDataEnabledListener stop() {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ return this;
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ mClient.onMobileDataEnabledChange();
+ }
+}
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 88ff5cf247f..ae31b5643a9 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -21,6 +21,9 @@ import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -35,6 +38,7 @@ import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.network.telephony.DataConnectivityListener;
import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -46,14 +50,18 @@ import java.util.Map;
* available if there are 2 or more subscriptions.
*/
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
- LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
+ LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
+ MobileDataEnabledListener.Client, DataConnectivityListener.Client {
private static final String TAG = "SubscriptionsPrefCntrlr";
private UpdateListener mUpdateListener;
private String mPreferenceGroupKey;
private PreferenceGroup mPreferenceGroup;
private SubscriptionManager mManager;
+ private ConnectivityManager mConnectivityManager;
private SubscriptionsChangeListener mSubscriptionsListener;
+ private MobileDataEnabledListener mDataEnabledListener;
+ private DataConnectivityListener mConnectivityListener;
// Map of subscription id to Preference
private Map mSubscriptionPreferences;
@@ -89,20 +97,27 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mPreferenceGroupKey = preferenceGroupKey;
mStartOrder = startOrder;
mManager = context.getSystemService(SubscriptionManager.class);
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
mSubscriptionPreferences = new ArrayMap<>();
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
+ mDataEnabledListener = new MobileDataEnabledListener(context, this);
+ mConnectivityListener = new DataConnectivityListener(context, this);
lifecycle.addObserver(this);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mSubscriptionsListener.start();
+ mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
+ mConnectivityListener.start();
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
mSubscriptionsListener.stop();
+ mDataEnabledListener.stop();
+ mConnectivityListener.stop();
}
@Override
@@ -158,6 +173,19 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mUpdateListener.onChildrenUpdated();
}
+ private boolean activeNetworkIsCellular() {
+ final Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ if (activeNetwork == null) {
+ return false;
+ }
+ final NetworkCapabilities networkCapabilities = mConnectivityManager.getNetworkCapabilities(
+ activeNetwork);
+ if (networkCapabilities == null) {
+ return false;
+ }
+ return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
+ }
+
/**
* The summary can have either 1 or 2 lines depending on which services (calls, SMS, data) this
* subscription is the default for.
@@ -187,10 +215,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
if (subId == dataDefaultSubId) {
final TelephonyManager telMgrForSub = mContext.getSystemService(
TelephonyManager.class).createForSubscriptionId(subId);
- final int dataState = telMgrForSub.getDataState();
- if (dataState == TelephonyManager.DATA_CONNECTED) {
+ boolean dataEnabled = telMgrForSub.isDataEnabled();
+ if (dataEnabled && activeNetworkIsCellular()) {
line2 = mContext.getString(R.string.mobile_data_active);
- } else if (!telMgrForSub.isDataEnabled()) {
+ } else if (!dataEnabled) {
line2 = mContext.getString(R.string.mobile_data_off);
} else {
line2 = mContext.getString(R.string.default_for_mobile_data);
@@ -231,6 +259,22 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
@Override
public void onSubscriptionsChanged() {
+ // See if we need to change which sub id we're using to listen for enabled/disabled changes.
+ int defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
+ if (defaultDataSubId != mDataEnabledListener.getSubId()) {
+ mDataEnabledListener.stop();
+ mDataEnabledListener.start(defaultDataSubId);
+ }
+ update();
+ }
+
+ @Override
+ public void onMobileDataEnabledChange() {
+ update();
+ }
+
+ @Override
+ public void onDataConnectivityChange() {
update();
}
}
diff --git a/src/com/android/settings/network/telephony/DataConnectivityListener.java b/src/com/android/settings/network/telephony/DataConnectivityListener.java
new file mode 100644
index 00000000000..adb39c64be0
--- /dev/null
+++ b/src/com/android/settings/network/telephony/DataConnectivityListener.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 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.telephony;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+
+/** A helper class to listen to a few different kinds of connectivity changes that could be relevant
+ * to changes in which network is active, and whether the active network has internet data
+ * connectivity. */
+public class DataConnectivityListener extends ConnectivityManager.NetworkCallback {
+ private Context mContext;
+ private ConnectivityManager mConnectivityManager;
+ private final NetworkRequest mNetworkRequest;
+ private Client mClient;
+
+ public interface Client {
+ void onDataConnectivityChange();
+ }
+
+ public DataConnectivityListener(Context context, Client client) {
+ mContext = context;
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ mClient = client;
+ mNetworkRequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+ }
+
+ public void start() {
+ mConnectivityManager.registerNetworkCallback(mNetworkRequest, this,
+ mContext.getMainThreadHandler());
+ }
+
+ public void stop() {
+ mConnectivityManager.unregisterNetworkCallback(this);
+ }
+
+ @Override
+ public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
+ final Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ if (activeNetwork != null && activeNetwork.equals(network)) {
+ mClient.onDataConnectivityChange();
+ }
+ }
+
+ @Override
+ public void onLosing(Network network, int maxMsToLive) {
+ mClient.onDataConnectivityChange();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ mClient.onDataConnectivityChange();
+ }
+}
diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
index 3f55003801f..b8a31fe1852 100644
--- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.java
@@ -21,9 +21,7 @@ import android.content.Intent;
import android.net.NetworkTemplate;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.text.format.Formatter;
import androidx.preference.Preference;
@@ -87,9 +85,10 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
mSubId = subId;
if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- mTemplate = getNetworkTemplate(mContext, subId);
+ mTemplate = DataUsageUtils.getDefaultTemplate(mContext, mSubId);
final DataUsageController controller = new DataUsageController(mContext);
+ controller.setSubscriptionId(mSubId);
mDataUsageInfo = controller.getDataUsageInfo(mTemplate);
mIntent = new Intent(Settings.ACTION_MOBILE_DATA_USAGE);
@@ -97,12 +96,4 @@ public class DataUsagePreferenceController extends TelephonyBasePreferenceContro
mIntent.putExtra(Settings.EXTRA_SUB_ID, mSubId);
}
}
-
- private NetworkTemplate getNetworkTemplate(Context context, int subId) {
- final TelephonyManager tm = TelephonyManager.from(context).createForSubscriptionId(subId);
- NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(tm.getSubscriberId());
-
- return NetworkTemplate.normalize(mobileAll, tm.getMergedSubscriberIds());
- }
-
}
diff --git a/src/com/android/settings/network/telephony/RoamingPreferenceController.java b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
index 4140d5d9709..dd5fd0e8fef 100644
--- a/src/com/android/settings/network/telephony/RoamingPreferenceController.java
+++ b/src/com/android/settings/network/telephony/RoamingPreferenceController.java
@@ -33,7 +33,6 @@ import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -114,8 +113,10 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
public void updateState(Preference preference) {
super.updateState(preference);
final RestrictedSwitchPreference switchPreference = (RestrictedSwitchPreference) preference;
- switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- switchPreference.setChecked(isChecked());
+ if (!switchPreference.isDisabledByAdmin()) {
+ switchPreference.setEnabled(mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ switchPreference.setChecked(isChecked());
+ }
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
index 94d12288d28..e1da707e543 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/TimeSpentInAppPreferenceControllerTest.java
@@ -20,6 +20,8 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -32,6 +34,7 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
@@ -58,10 +61,12 @@ public class TimeSpentInAppPreferenceControllerTest {
private ShadowPackageManager mPackageManager;
private TimeSpentInAppPreferenceController mController;
private Preference mPreference;
+ private FakeFeatureFactory mFeatureFactory;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mFeatureFactory = FakeFeatureFactory.setupForTest();
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new TimeSpentInAppPreferenceController(mContext, TEST_KEY);
@@ -112,4 +117,12 @@ public class TimeSpentInAppPreferenceControllerTest {
assertThat(intent.getStringExtra(EXTRA_PACKAGE_NAME))
.isEqualTo(TEST_INTENT.getStringExtra(EXTRA_PACKAGE_NAME));
}
+
+ @Test
+ public void getSummary_shouldQueryAppFeatureProvider() {
+ mController.getSummary();
+
+ verify(mFeatureFactory.applicationFeatureProvider).getTimeSpentInApp(
+ nullable(String.class));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/core/instrumentation/SettingsEventLogWriterTest.java b/tests/robotests/src/com/android/settings/core/instrumentation/SettingsEventLogWriterTest.java
new file mode 100644
index 00000000000..ba2553de517
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/core/instrumentation/SettingsEventLogWriterTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 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.core.instrumentation;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.metrics.LogMaker;
+import android.provider.DeviceConfig;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.settings.core.SettingsUIDeviceConfig;
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowDeviceConfig.class, SettingsEventLogWriterTest.ShadowMetricsLogger.class})
+public class SettingsEventLogWriterTest {
+
+ private SettingsEventLogWriter mWriter;
+
+ @Before
+ public void setUp() {
+ mWriter = new SettingsEventLogWriter();
+ }
+
+ @After
+ public void tearDown() {
+ ShadowDeviceConfig.reset();
+ ShadowMetricsLogger.reset();
+ }
+
+ @Test
+ public void visible_eventLogEnabled_shouldLog() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "true", true);
+
+ mWriter.visible(RuntimeEnvironment.application, SettingsEnums.PAGE_UNKNOWN,
+ SettingsEnums.SETTINGS_HOMEPAGE);
+
+ assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(1);
+ }
+
+ @Test
+ public void hidden_eventLogEnabled_shouldLog() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "true", true);
+
+ mWriter.hidden(RuntimeEnvironment.application, SettingsEnums.SETTINGS_HOMEPAGE);
+
+ assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(1);
+ }
+
+ @Test
+ public void visible_eventLogDisabled_shouldNotLog() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "false", true);
+
+ mWriter.visible(RuntimeEnvironment.application, SettingsEnums.PAGE_UNKNOWN,
+ SettingsEnums.SETTINGS_HOMEPAGE);
+
+ assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(0);
+ }
+
+ @Test
+ public void hidden_eventLogDisabled_shouldNotLog() {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SETTINGS_UI,
+ SettingsUIDeviceConfig.GENERIC_EVENT_LOGGING_ENABLED, "false", true);
+
+ mWriter.hidden(RuntimeEnvironment.application, SettingsEnums.SETTINGS_HOMEPAGE);
+
+ assertThat(ShadowMetricsLogger.sActionLoggedCount).isEqualTo(0);
+ }
+
+ @Implements(MetricsLogger.class)
+ public static class ShadowMetricsLogger {
+
+ public static int sActionLoggedCount = 0;
+
+ @Resetter
+ public static void reset() {
+ sActionLoggedCount = 0;
+ }
+
+ @Implementation
+ protected static void action(LogMaker content) {
+ sActionLoggedCount++;
+ }
+
+ @Implementation
+ public static void hidden(Context context, int category) throws IllegalArgumentException {
+ sActionLoggedCount++;
+ }
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
index 79c3ad10cbf..b9bfcc1e66a 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java
@@ -27,11 +27,13 @@ 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.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.NetworkPolicyManager;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import androidx.fragment.app.FragmentActivity;
@@ -44,6 +46,7 @@ import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
@@ -68,6 +71,8 @@ public class DataUsageSummaryTest {
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private NetworkStatsManager mNetworkStatsManager;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private TelephonyManager mTelephonyManager;
private Context mContext;
private FragmentActivity mActivity;
private SummaryLoader.SummaryProvider mSummaryProvider;
@@ -84,7 +89,9 @@ public class DataUsageSummaryTest {
ShadowUserManager.getShadow().setIsAdminUser(true);
shadowContext.setSystemService(Context.NETWORK_POLICY_SERVICE, mNetworkPolicyManager);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get());
doReturn(mNetworkStatsManager).when(mActivity).getSystemService(NetworkStatsManager.class);
diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
index 89388730742..69d1cbc8048 100644
--- a/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPreferenceControllerTest.java
@@ -21,6 +21,8 @@ import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
@@ -28,11 +30,12 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.provider.Settings;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.R;
-import com.android.settingslib.RestrictedPreference;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -41,7 +44,6 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
-@Ignore("b/130897305")
public class AdaptiveSleepPreferenceControllerTest {
private static final String PREFERENCE_KEY = "adaptive_sleep";
@@ -52,18 +54,25 @@ public class AdaptiveSleepPreferenceControllerTest {
@Mock
private PackageManager mPackageManager;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mContentResolver = mContext.getContentResolver();
- mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
-
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ when(mPackageManager.getAttentionServicePackageName()).thenReturn("some.package");
when(mPackageManager.checkPermission(any(), any())).thenReturn(
PackageManager.PERMISSION_GRANTED);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+
+ mController = new AdaptiveSleepPreferenceController(mContext, PREFERENCE_KEY);
}
@Test
@@ -145,8 +154,7 @@ public class AdaptiveSleepPreferenceControllerTest {
PackageManager.PERMISSION_DENIED);
mController.setChecked(true);
- final RestrictedPreference mPreference = new RestrictedPreference(mContext);
- mController.updateState(mPreference);
+ mController.displayPreference(mScreen);
assertThat(mPreference.isEnabled()).isFalse();
}
}
diff --git a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
index d0dbc0bb5e0..dfc13de8e14 100644
--- a/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/DisplayWhiteBalancePreferenceControllerTest.java
@@ -1,16 +1,27 @@
package com.android.settings.display;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ContentResolver;
+import android.content.Context;
import android.hardware.display.ColorDisplayManager;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
@@ -27,6 +38,15 @@ public class DisplayWhiteBalancePreferenceControllerTest {
@Mock
private ColorDisplayManager mColorDisplayManager;
+ private ContentResolver mContentResolver;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private Preference mPreference;
+
+ private final String PREFERENCE_KEY = "display_white_balance";
@After
public void tearDown() {
@@ -36,17 +56,21 @@ public class DisplayWhiteBalancePreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = spy(new DisplayWhiteBalancePreferenceController(RuntimeEnvironment.application,
- "display_white_balance"));
+
+ mContentResolver = RuntimeEnvironment.application.getContentResolver();
+ when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
+ when(mScreen.findPreference(PREFERENCE_KEY)).thenReturn(mPreference);
+
+ mController = spy(new DisplayWhiteBalancePreferenceController(mContext, PREFERENCE_KEY));
doReturn(mColorDisplayManager).when(mController).getColorDisplayManager();
}
@Test
- public void isAvailable_configuredAvailable() {
+ public void isAvailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+
assertThat(mController.isAvailable()).isTrue();
}
@@ -54,20 +78,7 @@ public class DisplayWhiteBalancePreferenceControllerTest {
public void isAvailable_configuredUnavailable() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
- assertThat(mController.isAvailable()).isFalse();
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
- assertThat(mController.isAvailable()).isFalse();
-
- SettingsShadowResources.overrideResource(
- com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
- when(mColorDisplayManager.getColorMode())
- .thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
assertThat(mController.isAvailable()).isFalse();
}
@@ -94,4 +105,101 @@ public class DisplayWhiteBalancePreferenceControllerTest {
when(mColorDisplayManager.isDisplayWhiteBalanceEnabled()).thenReturn(false);
assertThat(mController.isChecked()).isFalse();
}
+
+ @Test
+ public void onStart_configuredUnavailable() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, false);
+ mController.displayPreference(mScreen);
+ mController.onStart();
+ assertThat(mController.mContentObserver).isNull();
+ }
+
+ @Test
+ public void onStart_configuredAvailable() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ when(mColorDisplayManager.getColorMode())
+ .thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ toggleAccessibilityInversion(false);
+ toggleAccessibilityDaltonizer(false);
+
+ mController.displayPreference(mScreen);
+ mController.onStart();
+ assertThat(mController.mContentObserver).isNotNull();
+ }
+
+ @Test
+ public void visibility_configuredAvailableAccessibilityToggled() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ mController.displayPreference(mScreen);
+
+ // Accessibility features disabled
+ toggleAccessibilityInversion(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ toggleAccessibilityDaltonizer(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ // Accessibility features enabled one by one
+ toggleAccessibilityInversion(true);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ toggleAccessibilityDaltonizer(true);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ // Accessibility features disabled one by one
+ toggleAccessibilityInversion(false);
+ reset(mPreference);
+ mController.updateVisibility();
+ // Daltonizer is still enabled, so we expect the preference to still be invisible
+ verify(mPreference).setVisible(false);
+
+ // Now both a11y features are disabled, so we expect the preference to become visible
+ toggleAccessibilityDaltonizer(false);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+ }
+
+ @Test
+ public void visibility_configuredAvailableColorModeChanged() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_displayWhiteBalanceAvailable, true);
+ mController.displayPreference(mScreen);
+
+ // Non-Saturated color mode selected
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+
+ // Saturated color mode selected
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_SATURATED);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(false);
+
+ // Switch back to non-Saturated color mode
+ when(mColorDisplayManager.getColorMode()).thenReturn(ColorDisplayManager.COLOR_MODE_NATURAL);
+ reset(mPreference);
+ mController.updateVisibility();
+ verify(mPreference).setVisible(true);
+ }
+
+ private void toggleAccessibilityInversion(boolean enable) {
+ Settings.Secure.putInt(mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, enable ? 1 : 0);
+ }
+
+ private void toggleAccessibilityDaltonizer(boolean enable) {
+ Settings.Secure.putInt(mContentResolver,
+ Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, enable ? 1 : 0);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 2dd0d9be71e..4d77bddc45f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -15,6 +15,7 @@
*/
package com.android.settings.fuelgauge;
+import static com.android.settings.fuelgauge.PowerUsageSummary.BATTERY_INFO_LOADER;
import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_ADVANCED_BATTERY;
import static com.google.common.truth.Truth.assertThat;
@@ -373,6 +374,17 @@ public class PowerUsageSummaryTest {
mFragment.mSettingsObserver);
}
+ @Test
+ public void restartBatteryInfoLoader_contextNull_doNothing() {
+ when(mFragment.getContext()).thenReturn(null);
+ when(mFragment.getLoaderManager()).thenReturn(mLoaderManager);
+
+ mFragment.restartBatteryInfoLoader();
+
+ verify(mLoaderManager, never()).restartLoader(BATTERY_INFO_LOADER, Bundle.EMPTY,
+ mFragment.mBatteryInfoLoaderCallbacks);
+ }
+
public static class TestFragment extends PowerUsageSummary {
private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
index 03c9b0a69a4..5022d4a318f 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSeekBarControllerTest.java
@@ -7,9 +7,14 @@ import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
+
+import androidx.preference.PreferenceScreen;
+
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;
@@ -19,9 +24,12 @@ public class BatterySaverScheduleSeekBarControllerTest {
private Context mContext;
private ContentResolver mResolver;
private BatterySaverScheduleSeekBarController mController;
+ @Mock
+ private PreferenceScreen mScreen;
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = new BatterySaverScheduleSeekBarController(mContext);
mResolver = mContext.getContentResolver();
@@ -62,4 +70,14 @@ public class BatterySaverScheduleSeekBarControllerTest {
mController.updateSeekBar();
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
}
+
+ @Test
+ public void addToScreen_addsToEnd() {
+ Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
+ PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
+ Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
+ mController.addToScreen(mScreen);
+ assertThat(mController.mSeekBarPreference.getOrder()).isEqualTo(100);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java
new file mode 100644
index 00000000000..1fed7df6059
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/GlobalActionsPanelPreferenceControllerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2019 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.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+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 GlobalActionsPanelPreferenceControllerTest {
+
+ private Context mContext;
+ private GlobalActionsPanelPreferenceController mController;
+
+ private static final String KEY_GESTURE_PANEL = "gesture_global_actions_panel";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new GlobalActionsPanelPreferenceController(mContext, KEY_GESTURE_PANEL);
+ }
+
+ @Test
+ public void testIsChecked_panelEnabled() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), mController.ENABLED_SETTING, 1);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void testIsChecked_panelDisabled() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), mController.ENABLED_SETTING, 0);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void getAvailabilityStatus_panelAvailable() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), mController.AVAILABLE_SETTING, 1);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(mController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_panelUnavailable() {
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), mController.AVAILABLE_SETTING, 0);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(mController.CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void isSliceable_correctKey() {
+ final GlobalActionsPanelPreferenceController controller =
+ new GlobalActionsPanelPreferenceController(mContext, mController.TOGGLE_KEY);
+ assertThat(controller.isSliceable()).isTrue();
+ }
+
+ @Test
+ public void isSliceable_incorrectKey() {
+ final GlobalActionsPanelPreferenceController controller =
+ new GlobalActionsPanelPreferenceController(mContext, "bad_key");
+ assertThat(controller.isSliceable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
index a23f8dac26f..5c02101e057 100644
--- a/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationEdgeToEdgePreferenceControllerTest.java
@@ -130,6 +130,12 @@ public class SystemNavigationEdgeToEdgePreferenceControllerTest {
.isFalse();
}
+ @Test
+ public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
+ assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext,
+ "com.package.fake")).isFalse();
+ }
+
@Test
public void testIsChecked_defaultIsEdgeToEdge_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,
diff --git a/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
index dc9e3d9ae9a..ebb1eb019c4 100644
--- a/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationLegacyPreferenceControllerTest.java
@@ -130,6 +130,12 @@ public class SystemNavigationLegacyPreferenceControllerTest {
SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
+ @Test
+ public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
+ assertThat(SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext,
+ "com.package.fake")).isFalse();
+ }
+
@Test
public void testIsChecked_defaultIsLegacy_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,
diff --git a/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
index 955ea0c631f..f8a0b58a2f4 100644
--- a/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationSwipeUpPreferenceControllerTest.java
@@ -130,6 +130,12 @@ public class SystemNavigationSwipeUpPreferenceControllerTest {
.isFalse();
}
+ @Test
+ public void testIsGestureAvailable_noOverlayPackage_shouldReturnFalse() {
+ assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext,
+ "com.package.fake")).isFalse();
+ }
+
@Test
public void testIsChecked_defaultIsSwipeUp_shouldReturnTrue() {
SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode,
diff --git a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
index 50a798f744b..dcb32c4c475 100644
--- a/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/SettingsHomepageActivityTest.java
@@ -35,8 +35,6 @@ public class SettingsHomepageActivityTest {
public void setHomepageContainerPaddingTop_shouldBeSetPaddingTop() {
final SettingsHomepageActivity activity = Robolectric.buildActivity(
SettingsHomepageActivity.class).create().get();
- final int statusBarHeight = activity.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
final int searchBarHeight = activity.getResources().getDimensionPixelSize(
R.dimen.search_bar_height);
final int searchBarMargin = activity.getResources().getDimensionPixelSize(
@@ -46,8 +44,7 @@ public class SettingsHomepageActivityTest {
activity.setHomepageContainerPaddingTop();
final int actualPaddingTop = view.getPaddingTop();
- assertThat(actualPaddingTop).isEqualTo(
- statusBarHeight + searchBarHeight + searchBarMargin * 2);
+ assertThat(actualPaddingTop).isEqualTo(searchBarHeight + searchBarMargin * 2);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index 70761cf52d5..fb04dac9dd2 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -16,11 +16,13 @@
package com.android.settings.homepage.contextualcards.slices;
+import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
@@ -160,6 +162,15 @@ public class SliceContextualCardRendererTest {
assertThat(swipeBg.getVisibility()).isEqualTo(View.GONE);
}
+ @Test
+ public void bindView_deferredSetupCard_shouldNotCrash() {
+ final RecyclerView.ViewHolder viewHolder = getDeferredSetupViewHolder();
+ final ContextualCard card = buildContextualCard(TEST_SLICE_URI);
+ mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
+
+ mRenderer.bindView(viewHolder, card);
+ }
+
@Test
public void viewClick_keepCard_shouldShowSlice() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
@@ -246,6 +257,18 @@ public class SliceContextualCardRendererTest {
return mRenderer.createViewHolder(view, VIEW_TYPE_FULL_WIDTH);
}
+ private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
+ final RecyclerView recyclerView = new RecyclerView(mActivity);
+ recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
+ final View view = LayoutInflater.from(mActivity)
+ .inflate(VIEW_TYPE_DEFERRED_SETUP, recyclerView, false);
+ final RecyclerView.ViewHolder viewHolder = spy(
+ new SliceDeferredSetupCardRendererHelper.DeferredSetupCardViewHolder(view));
+ doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
+
+ return viewHolder;
+ }
+
private ContextualCard buildContextualCard(Uri sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")
diff --git a/tests/robotests/src/com/android/settings/network/DataConnectivityListenerTest.java b/tests/robotests/src/com/android/settings/network/DataConnectivityListenerTest.java
new file mode 100644
index 00000000000..b45e28c554c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/DataConnectivityListenerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2019 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 org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+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.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Handler;
+
+import com.android.settings.network.telephony.DataConnectivityListener;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class DataConnectivityListenerTest {
+ @Mock
+ private DataConnectivityListener.Client mClient;
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
+ private Network mActiveNetwork;
+
+ private Context mContext;
+ private DataConnectivityListener mListener;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
+ when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
+ mListener = new DataConnectivityListener(mContext, mClient);
+ }
+
+ @Test
+ public void noStart_doesNotRegister() {
+ verify(mConnectivityManager, never()).registerNetworkCallback(any(NetworkRequest.class),
+ any(ConnectivityManager.NetworkCallback.class), any(Handler.class));
+ }
+
+ @Test
+ public void start_doesRegister() {
+ mListener.start();
+ verify(mConnectivityManager).registerNetworkCallback(any(NetworkRequest.class),
+ eq(mListener), any(Handler.class));
+ }
+
+ @Test
+ public void onCapabilitiesChanged_notActiveNetwork_noCallback() {
+ Network changedNetwork = mock(Network.class);
+ mListener.onCapabilitiesChanged(changedNetwork, mock(NetworkCapabilities.class));
+ verify(mClient, never()).onDataConnectivityChange();
+ }
+
+ @Test
+ public void onCapabilitiesChanged_activeNetwork_onDataConnectivityChangeFires() {
+ mListener.onCapabilitiesChanged(mActiveNetwork, mock(NetworkCapabilities.class));
+ verify(mClient).onDataConnectivityChange();
+ }
+
+ @Test
+ public void onLosing_notActiveNetwork_onDataConnectivityChangeFires() {
+ Network changedNetwork = mock(Network.class);
+ mListener.onLosing(changedNetwork, 500);
+ verify(mClient).onDataConnectivityChange();
+ }
+
+ @Test
+ public void onLosing_activeNetwork_onDataConnectivityChangeFires() {
+ mListener.onLosing(mActiveNetwork, 500);
+ verify(mClient).onDataConnectivityChange();
+ }
+
+ @Test
+ public void onLost_notActiveNetwork_onDataConnectivityChangeFires() {
+ Network changedNetwork = mock(Network.class);
+ mListener.onLost(changedNetwork);
+ verify(mClient).onDataConnectivityChange();
+ }
+
+ @Test
+ public void onLost_activeNetwork_onDataConnectivityChangeFires() {
+ mListener.onLost(mActiveNetwork);
+ verify(mClient).onDataConnectivityChange();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/MobileDataEnabledListenerTest.java b/tests/robotests/src/com/android/settings/network/MobileDataEnabledListenerTest.java
new file mode 100644
index 00000000000..0824680bf88
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/MobileDataEnabledListenerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 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 org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.net.Uri;
+import android.provider.Settings;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class MobileDataEnabledListenerTest {
+ private static final int SUB_ID_ONE = 111;
+ private static final int SUB_ID_TWO = 222;
+
+ @Mock
+ private MobileDataEnabledListener.Client mClient;
+
+ private Context mContext;
+ private MobileDataEnabledListener mListener;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mListener = new MobileDataEnabledListener(mContext, mClient);
+ }
+
+ @Test
+ public void onMobileDataEnabledChange_firesCorrectly() {
+ mListener.start(SUB_ID_ONE);
+ final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_ONE);
+ mContext.getContentResolver().notifyChange(uri, null);
+ verify(mClient).onMobileDataEnabledChange();
+ }
+
+ @Test
+ public void onMobileDataEnabledChange_doesNotFireAfterStop() {
+ mListener.start(SUB_ID_ONE);
+ mListener.stop();
+ final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_ONE);
+ mContext.getContentResolver().notifyChange(uri, null);
+ verify(mClient, never()).onMobileDataEnabledChange();
+ }
+
+ @Test
+ public void onMobileDataEnabledChange_changedToDifferentId_firesCorrectly() {
+ mListener.start(SUB_ID_ONE);
+ mListener.stop();
+ mListener.start(SUB_ID_TWO);
+ final Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + SUB_ID_TWO);
+ mContext.getContentResolver().notifyChange(uri, null);
+ verify(mClient).onMobileDataEnabledChange();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 26f26ff5505..d6edcc72a87 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -33,6 +33,9 @@ import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -74,7 +77,13 @@ public class SubscriptionsPreferenceControllerTest {
@Mock
private SubscriptionManager mSubscriptionManager;
@Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
private TelephonyManager mTelephonyManager;
+ @Mock
+ private Network mActiveNetwork;
+ @Mock
+ private NetworkCapabilities mCapabilities;
private Context mContext;
private LifecycleOwner mLifecycleOwner;
@@ -90,7 +99,10 @@ public class SubscriptionsPreferenceControllerTest {
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+ when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
+ when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork)).thenReturn(mCapabilities);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mScreen.findPreference(eq(KEY))).thenReturn(mPreferenceCategory);
when(mPreferenceCategory.getContext()).thenReturn(mContext);
@@ -308,7 +320,8 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
- when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_CONNECTED);
+ when(mTelephonyManager.isDataEnabled()).thenReturn(true);
+ when(mCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
assertThat(mController.getSummary(11)).isEqualTo(
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
@@ -318,6 +331,27 @@ public class SubscriptionsPreferenceControllerTest {
mContext.getString(R.string.subscription_available));
}
+ @Test
+ public void getSummary_twoSubsOneDefaultForEverythingDataNotActive() {
+ final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
+ final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
+ when(sub1.getSubscriptionId()).thenReturn(11);
+ when(sub2.getSubscriptionId()).thenReturn(22);
+ SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
+
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
+ ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
+ ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
+ when(mTelephonyManager.isDataEnabled()).thenReturn(true);
+
+ assertThat(mController.getSummary(11)).isEqualTo(
+ mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
+ + mContext.getString(R.string.default_for_mobile_data));
+
+ assertThat(mController.getSummary(22)).isEqualTo(
+ mContext.getString(R.string.subscription_available));
+ }
+
@Test
public void getSummary_twoSubsOneDefaultForEverythingDataDisabled() {
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
@@ -329,7 +363,6 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
- when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_DISCONNECTED);
when(mTelephonyManager.isDataEnabled()).thenReturn(false);
assertThat(mController.getSummary(11)).isEqualTo(
@@ -351,7 +384,6 @@ public class SubscriptionsPreferenceControllerTest {
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(22);
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
- when(mTelephonyManager.getDataState()).thenReturn(TelephonyManager.DATA_DISCONNECTED);
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
assertThat(mController.getSummary(11)).isEqualTo(
diff --git a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
index ce61a898a6e..a883c51075b 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/RoamingPreferenceControllerTest.java
@@ -18,9 +18,12 @@ package com.android.settings.network.telephony;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyBoolean;
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.os.PersistableBundle;
@@ -76,7 +79,7 @@ public class RoamingPreferenceControllerTest {
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction();
- mPreference = new RestrictedSwitchPreference(mContext);
+ mPreference = spy(new RestrictedSwitchPreference(mContext));
mController = new RoamingPreferenceController(mContext, "roaming");
mController.init(mFragmentManager, SUB_ID);
mPreference.setKey(mController.getPreferenceKey());
@@ -140,4 +143,22 @@ public class RoamingPreferenceControllerTest {
assertThat(mPreference.isEnabled()).isTrue();
assertThat(mPreference.isChecked()).isTrue();
}
+
+ @Test
+ public void updateState_isNotDisabledByAdmin_shouldInvokeSetEnabled() {
+ when(mPreference.isDisabledByAdmin()).thenReturn(false);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference).setEnabled(anyBoolean());
+ }
+
+ @Test
+ public void updateState_isDisabledByAdmin_shouldNotInvokeSetEnabled() {
+ when(mPreference.isDisabledByAdmin()).thenReturn(true);
+
+ mController.updateState(mPreference);
+
+ verify(mPreference, never()).setEnabled(anyBoolean());
+ }
}