Show progress bar till the applyPayload returns am: 9be05afc88 am: 0aebae8d79
Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/2766345
Change-Id: Ibaf92a15e52ad5e7f1834210196c94d521ad90d4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 6576742..6edb5b7 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -114,7 +114,7 @@
settings:controller="com.android.settings.deviceinfo.HardwareInfoPreferenceController"/>
<!-- EID -->
- <com.android.settings.network.telephony.TelephonyPreferenceDialog
+ <com.android.settingslib.CustomDialogPreferenceCompat
android:key="eid_info"
android:order="31"
android:title="@string/status_eid"
diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java
index 9bf626c..4c65488 100644
--- a/src/com/android/settings/DefaultRingtonePreference.java
+++ b/src/com/android/settings/DefaultRingtonePreference.java
@@ -51,16 +51,9 @@
return;
}
- String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
- if (mimeType == null) {
+ if (!isValidRingtoneUri(ringtoneUri)) {
Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
- + " ignored: failure to find mimeType (no access from this context?)");
- return;
- }
-
- if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg"))) {
- Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri
- + " ignored: associated mimeType:" + mimeType + " is not an audio type");
+ + " ignored: invalid ringtone Uri");
return;
}
diff --git a/src/com/android/settings/RingtonePreference.java b/src/com/android/settings/RingtonePreference.java
index 8f9c618..de5b7c3 100644
--- a/src/com/android/settings/RingtonePreference.java
+++ b/src/com/android/settings/RingtonePreference.java
@@ -16,6 +16,8 @@
package com.android.settings;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
@@ -23,9 +25,11 @@
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings.System;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
@@ -239,4 +243,83 @@
return true;
}
+ public boolean isDefaultRingtone(Uri ringtoneUri) {
+ // null URIs are valid (None/silence)
+ return ringtoneUri == null || RingtoneManager.isDefault(ringtoneUri);
+ }
+
+ protected boolean isValidRingtoneUri(Uri ringtoneUri) {
+ if (isDefaultRingtone(ringtoneUri)) {
+ return true;
+ }
+
+ // Return early for android resource URIs
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(ringtoneUri.getScheme())) {
+ return true;
+ }
+
+ String mimeType = mUserContext.getContentResolver().getType(ringtoneUri);
+ if (mimeType == null) {
+ Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+ + " failed: failure to find mimeType (no access from this context?)");
+ return false;
+ }
+
+ if (!(mimeType.startsWith("audio/") || mimeType.equals("application/ogg")
+ || mimeType.equals("application/x-flac"))) {
+ Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+ + " failed: associated mimeType:" + mimeType + " is not an audio type");
+ return false;
+ }
+
+ // Validate userId from URIs: content://{userId}@...
+ final int userIdFromUri = ContentProvider.getUserIdFromUri(ringtoneUri, mUserId);
+ if (userIdFromUri != mUserId) {
+ final UserManager userManager = mUserContext.getSystemService(UserManager.class);
+
+ if (!userManager.isSameProfileGroup(mUserId, userIdFromUri)) {
+ Log.e(TAG,
+ "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + userIdFromUri
+ + " and user " + mUserId + " are not in the same profile group");
+ return false;
+ }
+
+ final int parentUserId;
+ final int profileUserId;
+ if (userManager.isProfile()) {
+ profileUserId = mUserId;
+ parentUserId = userIdFromUri;
+ } else {
+ parentUserId = mUserId;
+ profileUserId = userIdFromUri;
+ }
+
+ final UserHandle parent = userManager.getProfileParent(UserHandle.of(profileUserId));
+ if (parent == null || parent.getIdentifier() != parentUserId) {
+ Log.e(TAG,
+ "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + profileUserId
+ + " is not a profile of user " + parentUserId);
+ return false;
+ }
+
+ // Allow parent <-> managed profile sharing, unless restricted
+ if (userManager.hasUserRestrictionForUser(
+ UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, UserHandle.of(parentUserId))) {
+ Log.e(TAG,
+ "isValidRingtoneUri for URI:" + ringtoneUri + " failed: user " + parentUserId
+ + " has restriction: " + UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE);
+ return false;
+ }
+
+ if (!(userManager.isManagedProfile(profileUserId) || userManager.getUserProperties(
+ UserHandle.of(profileUserId)).isMediaSharedWithParent())) {
+ Log.e(TAG, "isValidRingtoneUri for URI:" + ringtoneUri
+ + " failed: user " + profileUserId + " is not a cloned or managed profile");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
}
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
index 70fdbf0..0bfb87d 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
@@ -76,6 +76,8 @@
private int mCenterTouchCount = 0;
+ private int mPace = 1;
+
@Nullable
UdfpsEnrollHelper.Listener mListener;
@@ -157,6 +159,9 @@
}
}
+ if (mRemainingSteps > remaining) {
+ mPace = mRemainingSteps - remaining;
+ }
mRemainingSteps = remaining;
if (mListener != null && mTotalSteps != -1) {
@@ -258,7 +263,7 @@
return false;
}
- return mRemainingSteps <= 2 && mRemainingSteps >= 0;
+ return mRemainingSteps <= mPace && mRemainingSteps >= 0;
}
private int getStageThresholdSteps(int totalSteps, int stageIndex) {
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
index 4d1b90b..e0376dc 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
+++ b/src/com/android/settings/deviceinfo/simstatus/SimEidPreferenceController.kt
@@ -21,16 +21,24 @@
import android.view.WindowManager
import android.widget.ImageView
import android.widget.TextView
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceScreen
import com.android.settings.R
import com.android.settings.core.BasePreferenceController
import com.android.settings.deviceinfo.PhoneNumberUtil
import com.android.settings.network.SubscriptionUtil
-import com.android.settings.network.telephony.TelephonyPreferenceDialog
+import com.android.settingslib.CustomDialogPreferenceCompat
import com.android.settingslib.Utils
import com.android.settingslib.qrcode.QrCodeGenerator
import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/**
* This is to show a preference regarding EID of SIM card.
@@ -41,7 +49,8 @@
BasePreferenceController(context, preferenceKey) {
private var slotSimStatus: SlotSimStatus? = null
private var eidStatus: EidStatus? = null
- private lateinit var preference: TelephonyPreferenceDialog
+ private lateinit var preference: CustomDialogPreferenceCompat
+ private var coroutineScope: CoroutineScope? = null
private lateinit var eid: String
fun init(slotSimStatus: SlotSimStatus?, eidStatus: EidStatus?) {
@@ -49,21 +58,48 @@
this.eidStatus = eidStatus
}
- override fun getAvailabilityStatus(): Int {
- if (!SubscriptionUtil.isSimHardwareVisible(mContext)) return UNSUPPORTED_ON_DEVICE
- eid = eidStatus?.eid ?: ""
- val isAvailable = mContext.userManager.isAdminUser &&
- !Utils.isWifiOnly(mContext) &&
- eid.isNotEmpty()
- return if (isAvailable) AVAILABLE else CONDITIONALLY_UNAVAILABLE
- }
+ /**
+ * Returns available here, if SIM hardware is visible.
+ *
+ * Also check [getIsAvailableAndUpdateEid] for other availability check which retrieved
+ * asynchronously later.
+ */
+ override fun getAvailabilityStatus() =
+ if (SubscriptionUtil.isSimHardwareVisible(mContext)) AVAILABLE else UNSUPPORTED_ON_DEVICE
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
preference = screen.findPreference(preferenceKey)!!
- val title = getTitle()
- preference.title = title
- preference.dialogTitle = title
+ }
+
+ override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+ coroutineScope = viewLifecycleOwner.lifecycleScope
+ coroutineScope?.launch {
+ viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
+ update()
+ }
+ }
+ }
+
+ private suspend fun update() {
+ val isAvailable = withContext(Dispatchers.Default) {
+ getIsAvailableAndUpdateEid()
+ }
+ preference.isVisible = isAvailable
+ if (isAvailable) {
+ val title = withContext(Dispatchers.Default) {
+ getTitle()
+ }
+ preference.title = title
+ preference.dialogTitle = title
+ updateDialog()
+ }
+ }
+
+ private fun getIsAvailableAndUpdateEid(): Boolean {
+ if (!mContext.userManager.isAdminUser || Utils.isWifiOnly(mContext)) return false
+ eid = eidStatus?.eid ?: ""
+ return eid.isNotEmpty()
}
/** Constructs title string. */
@@ -82,13 +118,7 @@
return mContext.getString(R.string.status_eid)
}
- override fun updateState(preference: Preference?) {
- super.updateState(preference)
-
- updateDialog()
- }
-
- private fun updateDialog() {
+ private suspend fun updateDialog() {
val dialog = preference.dialog ?: return
dialog.window?.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
@@ -106,11 +136,17 @@
}
override fun handlePreferenceTreeClick(preference: Preference): Boolean {
- if (preference.key == preferenceKey) {
- this.preference.setOnShowListener { updateDialog() }
- return true
+ if (preference.key != preferenceKey) return false
+ this.preference.setOnShowListener {
+ coroutineScope?.launch { updateDialog() }
}
- return super.handlePreferenceTreeClick(preference)
+ return true
+ }
+
+ override fun updateNonIndexableKeys(keys: MutableList<String>) {
+ if (!isAvailable() || !getIsAvailableAndUpdateEid()) {
+ keys += preferenceKey
+ }
}
companion object {
@@ -122,11 +158,13 @@
* @param eid is the EID string
* @return a Bitmap of QR code
*/
- private fun getEidQrCode(eid: String): Bitmap? = try {
- QrCodeGenerator.encodeQrCode(eid, QR_CODE_SIZE)
- } catch (exception: Exception) {
- Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
- null
+ private suspend fun getEidQrCode(eid: String): Bitmap? = withContext(Dispatchers.Default) {
+ try {
+ QrCodeGenerator.encodeQrCode(contents = eid, size = QR_CODE_SIZE)
+ } catch (exception: Exception) {
+ Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
+ null
+ }
}
}
}
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index 49a1a85..cc15e6e 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -58,22 +58,29 @@
public static final int INVALID_PORT_ID = -1;
@VisibleForTesting
- static class SimSlotChangeReceiver extends BroadcastReceiver{
+ static class SimCardStateChangeReceiver extends BroadcastReceiver{
private final CountDownLatch mLatch;
- SimSlotChangeReceiver(CountDownLatch latch) {
+ SimCardStateChangeReceiver(CountDownLatch latch) {
mLatch = latch;
}
public void registerOn(Context context) {
context.registerReceiver(this,
- new IntentFilter(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED),
- Context.RECEIVER_EXPORTED/*UNAUDITED*/);
+ new IntentFilter(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED),
+ Context.RECEIVER_NOT_EXPORTED);
}
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Action: " + intent.getAction());
- if (TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED.equals(intent.getAction())) {
+ if (!TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED.equals(intent.getAction())) {
+ return;
+ }
+ final int simState = intent.getIntExtra(
+ TelephonyManager.EXTRA_SIM_STATE, TelephonyManager.SIM_STATE_UNKNOWN);
+ Log.i(TAG, "simState: " + simState);
+ if (simState != TelephonyManager.SIM_STATE_UNKNOWN
+ && simState != TelephonyManager.SIM_STATE_ABSENT) {
mLatch.countDown();
}
}
@@ -269,8 +276,8 @@
try {
CountDownLatch latch = new CountDownLatch(1);
if (isMultipleEnabledProfilesSupported(telMgr)) {
- receiver = new SimSlotChangeReceiver(latch);
- ((SimSlotChangeReceiver) receiver).registerOn(context);
+ receiver = new SimCardStateChangeReceiver(latch);
+ ((SimCardStateChangeReceiver) receiver).registerOn(context);
} else {
receiver = new CarrierConfigChangedReceiver(latch);
((CarrierConfigChangedReceiver) receiver).registerOn(context);
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
index 5014634..453941d 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSwitchController.java
@@ -16,12 +16,16 @@
package com.android.settings.network.telephony;
+import static android.telephony.TelephonyManager.CALL_STATE_IDLE;
+
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
@@ -40,26 +44,40 @@
private int mSubId;
private SubscriptionsChangeListener mChangeListener;
private SubscriptionManager mSubscriptionManager;
+ private TelephonyManager mTelephonyManager;
+ private CallStateTelephonyCallback mCallStateCallback;
public MobileNetworkSwitchController(Context context, String preferenceKey) {
super(context, preferenceKey);
mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
mChangeListener = new SubscriptionsChangeListener(context, this);
}
void init(int subId) {
mSubId = subId;
+ mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
}
@OnLifecycleEvent(ON_RESUME)
public void onResume() {
mChangeListener.start();
+
+ if (mCallStateCallback == null) {
+ mCallStateCallback = new CallStateTelephonyCallback();
+ mTelephonyManager.registerTelephonyCallback(
+ mContext.getMainExecutor(), mCallStateCallback);
+ }
update();
}
@OnLifecycleEvent(ON_PAUSE)
public void onPause() {
+ if (mCallStateCallback != null) {
+ mTelephonyManager.unregisterTelephonyCallback(mCallStateCallback);
+ mCallStateCallback = null;
+ }
mChangeListener.stop();
}
@@ -118,4 +136,12 @@
public void onSubscriptionsChanged() {
update();
}
+
+ private class CallStateTelephonyCallback extends TelephonyCallback implements
+ TelephonyCallback.CallStateListener {
+ @Override
+ public void onCallStateChanged(int state) {
+ mSwitchBar.setSwitchBarEnabled(state == CALL_STATE_IDLE);
+ }
+ }
}
diff --git a/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java b/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
deleted file mode 100644
index 7dbef0c..0000000
--- a/src/com/android/settings/network/telephony/TelephonyPreferenceDialog.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022 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.util.AttributeSet;
-import com.android.settingslib.CustomDialogPreferenceCompat;
-
-/**
- * This is DialogPreference for supporting connectivity features.
- */
-public class TelephonyPreferenceDialog extends CustomDialogPreferenceCompat {
-
- public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public TelephonyPreferenceDialog(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public TelephonyPreferenceDialog(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public TelephonyPreferenceDialog(Context context) {
- super(context);
- }
-}
diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
index a6b565a..9ea8c58 100644
--- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
+++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
@@ -17,6 +17,7 @@
package com.android.settings.notification;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME;
@@ -26,6 +27,7 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.NotificationManager;
+import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
@@ -35,10 +37,12 @@
import android.content.pm.ServiceInfo;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.util.Slog;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
+import android.widget.Toast;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
@@ -55,12 +59,28 @@
private ComponentName mComponentName;
private NotificationManager mNm;
+ private DevicePolicyManager mDpm;
+ private UserManager mUm;
+
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ mUm = getSystemService(UserManager.class);
+ mDpm = getSystemService(DevicePolicyManager.class);
+
+ if (mUm.isManagedProfile()) {
+ Slog.w(LOG_TAG, "Apps in the work profile do not support notification listeners");
+ Toast.makeText(this,
+ mDpm.getResources().getString(WORK_APPS_CANNOT_ACCESS_NOTIFICATION_SETTINGS,
+ () -> getString(R.string.notification_settings_work_profile)),
+ Toast.LENGTH_SHORT).show();
+ finish();
+ return;
+ }
+
mNm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mComponentName = getIntent().getParcelableExtra(EXTRA_COMPONENT_NAME);
diff --git a/src/com/android/settings/notification/app/NotificationSoundPreference.java b/src/com/android/settings/notification/app/NotificationSoundPreference.java
index 136b21f..b55f9bd 100644
--- a/src/com/android/settings/notification/app/NotificationSoundPreference.java
+++ b/src/com/android/settings/notification/app/NotificationSoundPreference.java
@@ -25,10 +25,13 @@
import android.os.AsyncTask;
import android.util.AttributeSet;
+import android.util.Log;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
public class NotificationSoundPreference extends RingtonePreference {
+ private static final String TAG = "NotificationSoundPreference";
+
private Uri mRingtone;
public NotificationSoundPreference(Context context, AttributeSet attrs) {
@@ -50,8 +53,13 @@
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
- setRingtone(uri);
- callChangeListener(uri);
+ if (isValidRingtoneUri(uri)) {
+ setRingtone(uri);
+ callChangeListener(uri);
+ } else {
+ Log.e(TAG, "onActivityResult for URI:" + uri
+ + " ignored: invalid ringtone Uri");
+ }
}
return true;
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
index f4489c6..e123389 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/InteractAcrossProfilesDetailsPreferenceTest.kt
@@ -40,6 +40,7 @@
import com.android.settingslib.spaprivileged.framework.common.crossProfileApps
import org.junit.After
import org.junit.Before
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -116,6 +117,7 @@
composeTestRule.waitUntilExists(hasText(SUMMARY))
}
+ @Ignore
@Test
fun whenClick_startActivity() {
mockCanConfig(true)
diff --git a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
index 7877684..c580fc5 100644
--- a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
+++ b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java
@@ -16,16 +16,20 @@
package com.android.settings;
+import static org.mockito.ArgumentMatchers.any;
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.ContentInterface;
import android.content.ContentResolver;
import android.content.Context;
-import android.media.RingtoneManager;
+import android.content.pm.UserProperties;
import android.net.Uri;
+import android.os.UserHandle;
+import android.os.UserManager;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -34,17 +38,22 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
/** Unittest for DefaultRingtonePreference. */
@RunWith(AndroidJUnit4.class)
public class DefaultRingtonePreferenceTest {
+ private static final int OWNER_USER_ID = 1;
+ private static final int OTHER_USER_ID = 10;
+ private static final int INVALID_RINGTONE_TYPE = 0;
private DefaultRingtonePreference mDefaultRingtonePreference;
@Mock
private ContentResolver mContentResolver;
@Mock
+ private UserManager mUserManager;
private Uri mRingtoneUri;
@Before
@@ -52,14 +61,29 @@
MockitoAnnotations.initMocks(this);
Context context = spy(ApplicationProvider.getApplicationContext());
- doReturn(mContentResolver).when(context).getContentResolver();
+ mContentResolver = ContentResolver.wrap(Mockito.mock(ContentInterface.class));
+ when(context.getContentResolver()).thenReturn(mContentResolver);
mDefaultRingtonePreference = spy(new DefaultRingtonePreference(context, null /* attrs */));
doReturn(context).when(mDefaultRingtonePreference).getContext();
+
+ // Use INVALID_RINGTONE_TYPE to return early in RingtoneManager.setActualDefaultRingtoneUri
when(mDefaultRingtonePreference.getRingtoneType())
- .thenReturn(RingtoneManager.TYPE_RINGTONE);
- mDefaultRingtonePreference.setUserId(1);
+ .thenReturn(INVALID_RINGTONE_TYPE);
+
+ mDefaultRingtonePreference.setUserId(OWNER_USER_ID);
mDefaultRingtonePreference.mUserContext = context;
+ when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(false);
+
+ when(context.getSystemServiceName(UserManager.class)).thenReturn(Context.USER_SERVICE);
+ when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+
+ UserProperties userProperties = new UserProperties.Builder().setMediaSharedWithParent(false)
+ .build();
+ when(mUserManager.getUserProperties(UserHandle.of(OTHER_USER_ID))).thenReturn(
+ userProperties);
+
+ mRingtoneUri = Uri.parse("content://none");
}
@Test
@@ -79,4 +103,53 @@
verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
}
+
+ @Test
+ public void onSaveRingtone_notManagedProfile_shouldNotSetRingtone() {
+ mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+ when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+ when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
+ when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
+ UserHandle.of(OWNER_USER_ID));
+ when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(false);
+
+ mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+ verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
+ }
+
+ @Test
+ public void onSaveRingtone_notSameUser_shouldNotSetRingtone() {
+ mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+ when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+ when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(false);
+
+ mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+ verify(mDefaultRingtonePreference, never()).setActualDefaultRingtoneUri(mRingtoneUri);
+ }
+
+ @Test
+ public void onSaveRingtone_isManagedProfile_shouldSetRingtone() {
+ mRingtoneUri = Uri.parse("content://" + OTHER_USER_ID + "@ringtone");
+ when(mContentResolver.getType(mRingtoneUri)).thenReturn("audio/*");
+ when(mUserManager.isSameProfileGroup(OWNER_USER_ID, OTHER_USER_ID)).thenReturn(true);
+ when(mUserManager.getProfileParent(UserHandle.of(OTHER_USER_ID))).thenReturn(
+ UserHandle.of(OWNER_USER_ID));
+ when(mUserManager.isManagedProfile(OTHER_USER_ID)).thenReturn(true);
+
+ mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+ verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
+ }
+
+ @Test
+ public void onSaveRingtone_defaultUri_shouldSetRingtone() {
+ mRingtoneUri = Uri.parse("default_ringtone");
+ when(mDefaultRingtonePreference.isDefaultRingtone(any(Uri.class))).thenReturn(true);
+
+ mDefaultRingtonePreference.onSaveRingtone(mRingtoneUri);
+
+ verify(mDefaultRingtonePreference).setActualDefaultRingtoneUri(mRingtoneUri);
+ }
}
diff --git a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
index 2e17fb2..5261b3e 100644
--- a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
@@ -752,11 +752,14 @@
}
@Test
- public void onReceiveSimSlotChangeReceiver_receiveAction_timerCountDown() {
+ public void onReceiveSimCardStateChangeReceiver_receiveAction_timerCountDown() {
CountDownLatch latch = spy(new CountDownLatch(1));
- UiccSlotUtil.SimSlotChangeReceiver receive = new UiccSlotUtil.SimSlotChangeReceiver(latch);
+ UiccSlotUtil.SimCardStateChangeReceiver receive =
+ new UiccSlotUtil.SimCardStateChangeReceiver(latch);
+ Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, TelephonyManager.SIM_STATE_PRESENT);
- receive.onReceive(mContext, new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED));
+ receive.onReceive(mContext, intent);
verify(latch).countDown();
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
index e460d67..3cdd23a 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkSwitchControllerTest.java
@@ -35,6 +35,8 @@
import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
@@ -44,28 +46,32 @@
import androidx.preference.PreferenceViewHolder;
import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.widget.SettingsMainSwitchPreference;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.Arrays;
+import java.util.concurrent.Executor;
-@RunWith(AndroidJUnit4.class)
public class MobileNetworkSwitchControllerTest {
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
@Mock
private SubscriptionManager mSubscriptionManager;
@Mock
private SubscriptionInfo mSubscription;
+ @Mock
+ private TelephonyManager mTelephonyManager;
private PreferenceScreen mScreen;
private PreferenceManager mPreferenceManager;
@@ -76,7 +82,9 @@
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
@@ -89,18 +97,19 @@
when(sub2.getSubscriptionId()).thenReturn(456);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription, sub2));
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.createForSubscriptionId(mSubId))
+ .thenReturn(mTelephonyManager);
+
final String key = "prefKey";
mController = new MobileNetworkSwitchController(mContext, key);
mController.init(mSubscription.getSubscriptionId());
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
mPreferenceManager = new PreferenceManager(mContext);
mScreen = mPreferenceManager.createPreferenceScreen(mContext);
mSwitchBar = new SettingsMainSwitchPreference(mContext);
mSwitchBar.setKey(key);
+ mSwitchBar.setTitle("123");
mScreen.addPreference(mSwitchBar);
final LayoutInflater inflater = LayoutInflater.from(mContext);
@@ -117,7 +126,6 @@
@Test
@UiThreadTest
- @Ignore
public void isAvailable_pSIM_isNotAvailable() {
when(mSubscription.isEmbedded()).thenReturn(false);
mController.displayPreference(mScreen);
@@ -130,7 +138,6 @@
@Test
@UiThreadTest
- @Ignore
public void displayPreference_oneEnabledSubscription_switchBarNotHidden() {
doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
@@ -140,7 +147,6 @@
@Test
@UiThreadTest
- @Ignore
public void displayPreference_oneDisabledSubscription_switchBarNotHidden() {
doReturn(false).when(mSubscriptionManager).isActiveSubscriptionId(mSubId);
SubscriptionUtil.setAvailableSubscriptionsForTesting(Arrays.asList(mSubscription));
@@ -152,7 +158,6 @@
@Test
@UiThreadTest
- @Ignore
public void displayPreference_subscriptionEnabled_switchIsOn() {
when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
mController.displayPreference(mScreen);
@@ -162,7 +167,6 @@
@Test
@UiThreadTest
- @Ignore
public void displayPreference_subscriptionDisabled_switchIsOff() {
when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
@@ -174,7 +178,6 @@
@Test
@UiThreadTest
- @Ignore
public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledCalledCorrectly() {
when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(true);
mController.displayPreference(mScreen);
@@ -183,18 +186,24 @@
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivity(intentCaptor.capture());
+
+ // set switch off then should start a Activity.
mSwitchBar.setChecked(false);
+
+ when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
+ // Simulate action of back from previous activity.
+ mController.displayPreference(mScreen);
Bundle extra = intentCaptor.getValue().getExtras();
verify(mContext, times(1)).startActivity(any());
assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable))
.isEqualTo(false);
+ assertThat(mSwitchBar.isChecked()).isFalse();
}
@Test
@UiThreadTest
- @Ignore
public void switchChangeListener_fromEnabledToDisabled_setSubscriptionEnabledFailed() {
when(mSubscriptionManager.setSubscriptionEnabled(eq(mSubId), anyBoolean()))
.thenReturn(false);
@@ -205,7 +214,12 @@
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivity(intentCaptor.capture());
+
+ // set switch off then should start a Activity.
mSwitchBar.setChecked(false);
+
+ // Simulate action of back from previous activity.
+ mController.displayPreference(mScreen);
Bundle extra = intentCaptor.getValue().getExtras();
verify(mContext, times(1)).startActivity(any());
@@ -217,7 +231,6 @@
@Test
@UiThreadTest
- @Ignore
public void switchChangeListener_fromDisabledToEnabled_setSubscriptionEnabledCalledCorrectly() {
when(mSubscriptionManager.isActiveSubscriptionId(mSubId)).thenReturn(false);
mController.displayPreference(mScreen);
@@ -233,4 +246,24 @@
assertThat(extra.getInt(ToggleSubscriptionDialogActivity.ARG_SUB_ID)).isEqualTo(mSubId);
assertThat(extra.getBoolean(ToggleSubscriptionDialogActivity.ARG_enable)).isEqualTo(true);
}
+ @Test
+ @UiThreadTest
+ public void onResumeAndonPause_registerAndUnregisterTelephonyCallback() {
+ mController.onResume();
+
+ verify(mTelephonyManager)
+ .registerTelephonyCallback(any(Executor.class), any(TelephonyCallback.class));
+
+ mController.onPause();
+ verify(mTelephonyManager)
+ .unregisterTelephonyCallback(any(TelephonyCallback.class));
+ }
+
+ @Test
+ @UiThreadTest
+ public void onPause_doNotRegisterAndUnregisterTelephonyCallback() {
+ mController.onPause();
+ verify(mTelephonyManager, times(0))
+ .unregisterTelephonyCallback(any(TelephonyCallback.class));
+ }
}