diff --git a/src/com/android/settings/DefaultRingtonePreference.java b/src/com/android/settings/DefaultRingtonePreference.java index 824a5a05dc1..9bf626c9898 100644 --- a/src/com/android/settings/DefaultRingtonePreference.java +++ b/src/com/android/settings/DefaultRingtonePreference.java @@ -51,7 +51,7 @@ public class DefaultRingtonePreference extends RingtonePreference { return; } - String mimeType = getContext().getContentResolver().getType(ringtoneUri); + String mimeType = mUserContext.getContentResolver().getType(ringtoneUri); if (mimeType == null) { Log.e(TAG, "onSaveRingtone for URI:" + ringtoneUri + " ignored: failure to find mimeType (no access from this context?)"); diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index bb217a0d20a..1a9bdc742fe 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -466,6 +466,15 @@ public class SettingsActivity extends SettingsBaseActivity return false; } + // If the activity's launch mode is "singleInstance", it can't be embedded in Settings since + // it will be created in a new task. + ActivityInfo info = intent.resolveActivityInfo(getPackageManager(), + PackageManager.MATCH_DEFAULT_ONLY); + if (info.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { + Log.w(LOG_TAG, "launchMode: singleInstance"); + return false; + } + if (intent.getBooleanExtra(EXTRA_IS_FROM_SLICE, false)) { // Slice deep link starts the Intent using SubSettingLauncher. Returns true to show // 2-pane deep link. diff --git a/src/com/android/settings/datausage/AppDataUsage.java b/src/com/android/settings/datausage/AppDataUsage.java index f0d27997ff8..d57a2a18f79 100644 --- a/src/com/android/settings/datausage/AppDataUsage.java +++ b/src/com/android/settings/datausage/AppDataUsage.java @@ -40,6 +40,8 @@ import androidx.loader.content.Loader; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; import androidx.preference.PreferenceCategory; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settings.applications.AppInfoBase; @@ -105,6 +107,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC private Context mContext; private ArrayList mCycles; private long mSelectedCycle; + private boolean mIsLoading; @Override public void onCreate(Bundle icicle) { @@ -226,6 +229,16 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC @Override public void onResume() { super.onResume(); + // No animations will occur before: + // - LOADER_APP_USAGE_DATA initially updates the cycle + // - updatePrefs() initially updates the preference visibility + // This is mainly for the cycle spinner, because when the page is entered from the + // AppInfoDashboardFragment, there is no way to know whether the cycle data is available + // before finished the async loading. + // The animator will be set back if any page updates happens after loading, in + // setBackPreferenceListAnimatorIfLoaded(). + mIsLoading = true; + getListView().setItemAnimator(null); if (mDataSaverBackend != null) { mDataSaverBackend.addListener(this); } @@ -297,7 +310,25 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } + /** + * Sets back the preference list's animator if the loading is finished. + * + * The preference list's animator was temporarily removed before loading in onResume(). + * When need to update the preference visibility in this page after the loading, adding the + * animator back to keeping the usual animations. + */ + private void setBackPreferenceListAnimatorIfLoaded() { + if (mIsLoading) { + return; + } + RecyclerView recyclerView = getListView(); + if (recyclerView.getItemAnimator() == null) { + recyclerView.setItemAnimator(new DefaultItemAnimator()); + } + } + private void updatePrefs(boolean restrictBackground, boolean unrestrictData) { + setBackPreferenceListAnimatorIfLoaded(); final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMeteredDataRestricted( mContext, mPackageName, UserHandle.getUserId(mAppItem.key)); if (mRestrictBackground != null) { @@ -448,6 +479,7 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } else { bindData(0 /* position */); } + mIsLoading = false; } @Override diff --git a/src/com/android/settings/datausage/AppDataUsagePreference.java b/src/com/android/settings/datausage/AppDataUsagePreference.java index 3025a49bb6c..28058198d1a 100644 --- a/src/com/android/settings/datausage/AppDataUsagePreference.java +++ b/src/com/android/settings/datausage/AppDataUsagePreference.java @@ -20,6 +20,7 @@ import android.widget.ProgressBar; import androidx.preference.PreferenceViewHolder; +import com.android.settings.R; import com.android.settingslib.AppItem; import com.android.settingslib.net.UidDetail; import com.android.settingslib.net.UidDetailProvider; @@ -49,6 +50,9 @@ public class AppDataUsagePreference extends AppPreference { if (mDetail != null) { setAppInfo(); } else { + // Set a placeholder title before starting to fetch real title, this is necessary + // to avoid preference height change. + setTitle(R.string.summary_placeholder); ThreadUtils.postOnBackgroundThread(() -> { mDetail = provider.getUidDetail(mItem.key, true /* blocking */); ThreadUtils.postOnMainThread(() -> setAppInfo()); diff --git a/src/com/android/settings/network/EnableMultiSimSidecar.java b/src/com/android/settings/network/EnableMultiSimSidecar.java index 5545a69dd21..aefd55f00e8 100644 --- a/src/com/android/settings/network/EnableMultiSimSidecar.java +++ b/src/com/android/settings/network/EnableMultiSimSidecar.java @@ -190,8 +190,7 @@ public class EnableMultiSimSidecar extends AsyncTaskSidecar { Set activeRemovableLogicalSlotIds = new ArraySet<>(); for (UiccSlotInfo info : infos) { for (UiccPortInfo portInfo :info.getPorts()) { - if (info != null && portInfo.isActive() && info.isRemovable() - && !info.getIsEuicc()) { + if (info != null && portInfo.isActive() && info.isRemovable()) { activeRemovableLogicalSlotIds.add(portInfo.getLogicalSlotIndex()); } } diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java index 4c8a7d5f999..c9c52cb5c99 100644 --- a/src/com/android/settings/network/UiccSlotUtil.java +++ b/src/com/android/settings/network/UiccSlotUtil.java @@ -249,7 +249,6 @@ public class UiccSlotUtil { if (slotId == INVALID_PHYSICAL_SLOT_ID) { for (int i = 0; i < slots.length; i++) { if (slots[i].isRemovable() - && !slots[i].getIsEuicc() && !slots[i].getPorts().stream().findFirst().get().isActive() && slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_ERROR && slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_RESTRICTED) { diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java index f632a71119d..f5f18b4b9ee 100644 --- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java +++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java @@ -592,7 +592,6 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc .anyMatch( slot -> slot != null && slot.isRemovable() - && !slot.getIsEuicc() && slot.getPorts().stream().anyMatch( port -> port.isActive()) && slot.getCardStateInfo() diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java index da3db8b1369..4a6b96c1fa3 100644 --- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java +++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java @@ -294,7 +294,7 @@ public class SimSlotChangeHandler { return null; } for (UiccSlotInfo slotInfo : slotInfos) { - if (slotInfo != null && slotInfo.isRemovable() && !slotInfo.getIsEuicc()) { + if (slotInfo != null && slotInfo.isRemovable()) { return slotInfo; } } diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java index 14431ee5e69..483d74638a7 100644 --- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java @@ -48,6 +48,7 @@ import androidx.fragment.app.FragmentActivity; import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import androidx.recyclerview.widget.RecyclerView; import com.android.settings.applications.AppInfoBase; import com.android.settings.testutils.FakeFeatureFactory; @@ -240,6 +241,7 @@ public class AppDataUsageTest { ReflectionHelpers.setField(mFragment, "mUnrestrictedData", unrestrictedDataPref); ReflectionHelpers.setField(mFragment, "mDataSaverBackend", dataSaverBackend); ReflectionHelpers.setField(mFragment.services, "mPolicyManager", networkPolicyManager); + when(mFragment.getListView()).thenReturn(mock(RecyclerView.class)); ShadowRestrictedLockUtilsInternal.setRestricted(true); doReturn(NetworkPolicyManager.POLICY_NONE).when(networkPolicyManager) diff --git a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java index b9dea0167b5..7877684dce6 100644 --- a/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java +++ b/tests/unit/src/com/android/settings/DefaultRingtonePreferenceTest.java @@ -59,6 +59,7 @@ public class DefaultRingtonePreferenceTest { when(mDefaultRingtonePreference.getRingtoneType()) .thenReturn(RingtoneManager.TYPE_RINGTONE); mDefaultRingtonePreference.setUserId(1); + mDefaultRingtonePreference.mUserContext = context; } @Test