Snap for 9781601 from f0c3812123 to udc-release

Change-Id: Ib62514e1789ecc564d9d57fe30e05b9b089a6f88
This commit is contained in:
Android Build Coastguard Worker
2023-03-21 03:27:33 +00:00
26 changed files with 486 additions and 263 deletions

View File

@@ -96,4 +96,11 @@
android:summary="@string/demote_conversation_summary" android:summary="@string/demote_conversation_summary"
settings:allowDividerAbove="true"/> settings:allowDividerAbove="true"/>
<!-- only used in ChannelPanelActivity -->
<Preference
android:key="convo_promote"
android:icon="@drawable/ic_promote_conversation"
android:title="@string/promote_conversation_title"
android:summary="@string/promote_conversation_summary" />
</PreferenceScreen> </PreferenceScreen>

View File

@@ -437,7 +437,8 @@ public class AppInfoDashboardFragment extends DashboardFragment
} }
} }
private static void showLockScreen(Context context, Runnable successRunnable) { /** Shows the lock screen if the keyguard is secured. */
public static void showLockScreen(Context context, Runnable successRunnable) {
final KeyguardManager keyguardManager = context.getSystemService( final KeyguardManager keyguardManager = context.getSystemService(
KeyguardManager.class); KeyguardManager.class);

View File

@@ -207,7 +207,7 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
} }
// Build the pref and add it to the output & group. // Build the pref and add it to the output & group.
SwitchPreference pref = addProviderPreference(context, title, icon, packageName); SwitchPreference pref = addProviderPreference(context, title, icon, packageName, firstInfo.getSettingsSubtitle());
output.put(packageName, pref); output.put(packageName, pref);
group.addPreference(pref); group.addPreference(pref);
} }
@@ -223,7 +223,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
context, context,
label == null ? "" : label, label == null ? "" : label,
service.getServiceIcon(mContext), service.getServiceIcon(mContext),
service.getServiceInfo().packageName); service.getServiceInfo().packageName,
service.getSettingsSubtitle());
} }
/** /**
@@ -281,7 +282,8 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
@NonNull Context prefContext, @NonNull Context prefContext,
@NonNull CharSequence title, @NonNull CharSequence title,
@Nullable Drawable icon, @Nullable Drawable icon,
@NonNull String packageName) { @NonNull String packageName,
@Nullable CharSequence subtitle) {
final SwitchPreference pref = new SwitchPreference(prefContext); final SwitchPreference pref = new SwitchPreference(prefContext);
pref.setTitle(title); pref.setTitle(title);
pref.setChecked(mEnabledPackageNames.contains(packageName)); pref.setChecked(mEnabledPackageNames.contains(packageName));
@@ -290,6 +292,10 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
pref.setIcon(Utils.getSafeIcon(icon)); pref.setIcon(Utils.getSafeIcon(icon));
} }
if (subtitle != null) {
pref.setSummary(subtitle);
}
pref.setOnPreferenceClickListener( pref.setOnPreferenceClickListener(
p -> { p -> {
boolean isChecked = pref.isChecked(); boolean isChecked = pref.isChecked();

View File

@@ -20,6 +20,7 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.os.Bundle; import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@@ -106,6 +107,10 @@ public class SimStatusDialogFragment extends InstrumentedDialogFragment {
.sorted().toArray(); .sorted().toArray();
public void setText(int viewId, CharSequence text) { public void setText(int viewId, CharSequence text) {
if (!isAdded()) {
Log.d(TAG, "Fragment not attached yet.");
return;
}
setText(viewId, text, true); setText(viewId, text, true);
} }

View File

@@ -32,7 +32,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.preference.ListPreference; import androidx.preference.ListPreference;
@@ -51,9 +50,6 @@ public class InactiveApps extends SettingsPreferenceFragment
private static final CharSequence[] FULL_SETTABLE_BUCKETS_NAMES = private static final CharSequence[] FULL_SETTABLE_BUCKETS_NAMES =
{"ACTIVE", "WORKING_SET", "FREQUENT", "RARE", "RESTRICTED"}; {"ACTIVE", "WORKING_SET", "FREQUENT", "RARE", "RESTRICTED"};
private static final CharSequence[] REDUCED_SETTABLE_BUCKETS_NAMES =
Arrays.copyOfRange(FULL_SETTABLE_BUCKETS_NAMES, 0, 4);
private static final CharSequence[] FULL_SETTABLE_BUCKETS_VALUES = { private static final CharSequence[] FULL_SETTABLE_BUCKETS_VALUES = {
Integer.toString(STANDBY_BUCKET_ACTIVE), Integer.toString(STANDBY_BUCKET_ACTIVE),
Integer.toString(STANDBY_BUCKET_WORKING_SET), Integer.toString(STANDBY_BUCKET_WORKING_SET),
@@ -62,9 +58,6 @@ public class InactiveApps extends SettingsPreferenceFragment
Integer.toString(STANDBY_BUCKET_RESTRICTED) Integer.toString(STANDBY_BUCKET_RESTRICTED)
}; };
private static final CharSequence[] REDUCED_SETTABLE_BUCKETS_VALUES =
Arrays.copyOfRange(FULL_SETTABLE_BUCKETS_VALUES, 0, 4);
private UsageStatsManager mUsageStats; private UsageStatsManager mUsageStats;
@Override @Override
@@ -94,13 +87,8 @@ public class InactiveApps extends SettingsPreferenceFragment
final Context context = getActivity(); final Context context = getActivity();
final PackageManager pm = context.getPackageManager(); final PackageManager pm = context.getPackageManager();
final String settingsPackage = context.getPackageName(); final String settingsPackage = context.getPackageName();
final boolean allowRestrictedBucket = Settings.Global.getInt(getContentResolver(), final CharSequence[] bucketNames = FULL_SETTABLE_BUCKETS_NAMES;
Settings.Global.ENABLE_RESTRICTED_BUCKET, final CharSequence[] bucketValues = FULL_SETTABLE_BUCKETS_VALUES;
Settings.Global.DEFAULT_ENABLE_RESTRICTED_BUCKET) == 1;
final CharSequence[] bucketNames = allowRestrictedBucket
? FULL_SETTABLE_BUCKETS_NAMES : REDUCED_SETTABLE_BUCKETS_NAMES;
final CharSequence[] bucketValues = allowRestrictedBucket
? FULL_SETTABLE_BUCKETS_VALUES : REDUCED_SETTABLE_BUCKETS_VALUES;
Intent launcherIntent = new Intent(Intent.ACTION_MAIN); Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER); launcherIntent.addCategory(Intent.CATEGORY_LAUNCHER);

View File

@@ -101,7 +101,7 @@ public class InternetPreferenceController extends AbstractPreferenceController i
mInternetUpdater = new InternetUpdater(context, lifecycle, this); mInternetUpdater = new InternetUpdater(context, lifecycle, this);
mInternetType = mInternetUpdater.getInternetType(); mInternetType = mInternetUpdater.getInternetType();
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
lifecycle.addObserver(this); lifecycle.addObserver(this);
} }
@@ -156,14 +156,16 @@ public class InternetPreferenceController extends AbstractPreferenceController i
/** @OnLifecycleEvent(ON_RESUME) */ /** @OnLifecycleEvent(ON_RESUME) */
@OnLifecycleEvent(ON_RESUME) @OnLifecycleEvent(ON_RESUME)
public void onResume() { public void onResume() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mMobileNetworkRepository.updateEntity();
mSummaryHelper.register(true); mSummaryHelper.register(true);
} }
/** @OnLifecycleEvent(ON_PAUSE) */ /** @OnLifecycleEvent(ON_PAUSE) */
@OnLifecycleEvent(ON_PAUSE) @OnLifecycleEvent(ON_PAUSE)
public void onPause() { public void onPause() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
mSummaryHelper.register(false); mSummaryHelper.register(false);
} }

View File

@@ -20,6 +20,7 @@ import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
import static com.android.internal.telephony.TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED; import static com.android.internal.telephony.TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED;
import android.annotation.NonNull;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -56,10 +57,12 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import androidx.annotation.GuardedBy;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
@@ -72,14 +75,17 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static ExecutorService sExecutor = Executors.newSingleThreadExecutor(); private static ExecutorService sExecutor = Executors.newSingleThreadExecutor();
private static Map<String, SubscriptionInfoEntity> sCacheSubscriptionInfoEntityMap = private static Map<Integer, SubscriptionInfoEntity> sCacheSubscriptionInfoEntityMap =
new ArrayMap<>(); new ArrayMap<>();
private static Map<String, MobileNetworkInfoEntity> sCacheMobileNetworkInfoEntityMap = private static Map<Integer, MobileNetworkInfoEntity> sCacheMobileNetworkInfoEntityMap =
new ArrayMap<>(); new ArrayMap<>();
private static Map<String, UiccInfoEntity> sCacheUiccInfoEntityMap = new ArrayMap<>(); private static Map<Integer, UiccInfoEntity> sCacheUiccInfoEntityMap = new ArrayMap<>();
private static Collection<MobileNetworkCallback> sCallbacks = new CopyOnWriteArrayList<>();
private static final Object sInstanceLock = new Object();
@GuardedBy("sInstanceLock")
private static MobileNetworkRepository sInstance;
private SubscriptionManager mSubscriptionManager; private SubscriptionManager mSubscriptionManager;
private TelephonyManager mTelephonyManager;
private MobileNetworkDatabase mMobileNetworkDatabase; private MobileNetworkDatabase mMobileNetworkDatabase;
private SubscriptionInfoDao mSubscriptionInfoDao; private SubscriptionInfoDao mSubscriptionInfoDao;
private UiccInfoDao mUiccInfoDao; private UiccInfoDao mUiccInfoDao;
@@ -88,7 +94,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
private List<SubscriptionInfoEntity> mActiveSubInfoEntityList = new ArrayList<>(); private List<SubscriptionInfoEntity> mActiveSubInfoEntityList = new ArrayList<>();
private List<UiccInfoEntity> mUiccInfoEntityList = new ArrayList<>(); private List<UiccInfoEntity> mUiccInfoEntityList = new ArrayList<>();
private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>(); private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
private MobileNetworkCallback mCallback;
private Context mContext; private Context mContext;
private AirplaneModeObserver mAirplaneModeObserver; private AirplaneModeObserver mAirplaneModeObserver;
private Uri mAirplaneModeSettingUri; private Uri mAirplaneModeSettingUri;
@@ -100,35 +105,34 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT; private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
private int mPortIndex = TelephonyManager.INVALID_PORT_INDEX; private int mPortIndex = TelephonyManager.INVALID_PORT_INDEX;
private int mCardId = TelephonyManager.UNINITIALIZED_CARD_ID; private int mCardId = TelephonyManager.UNINITIALIZED_CARD_ID;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mIsEuicc = false; private boolean mIsEuicc = false;
private boolean mIsRemovable = false; private boolean mIsRemovable = false;
private boolean mIsActive = false; private boolean mIsActive = false;
private Map<Integer, SubscriptionInfo> mSubscriptionInfoMap = new ArrayMap<>(); private Map<Integer, SubscriptionInfo> mSubscriptionInfoMap = new ArrayMap<>();
private Map<Integer, TelephonyManager> mTelephonyManagerMap = new HashMap<>(); private Map<Integer, TelephonyManager> mTelephonyManagerMap = new HashMap<>();
private Map<Integer, PhoneCallStateTelephonyCallback> mTelephonyCallbackMap = new HashMap<>(); private Map<Integer, PhoneCallStateTelephonyCallback> mTelephonyCallbackMap = new HashMap<>();
private BroadcastReceiver mDataSubscriptionChangedReceiver = null;
public static MobileNetworkRepository create(Context context, @NonNull
MobileNetworkCallback mobileNetworkCallback) { public static MobileNetworkRepository getInstance(Context context) {
return new MobileNetworkRepository(context, mobileNetworkCallback, synchronized (sInstanceLock) {
SubscriptionManager.INVALID_SUBSCRIPTION_ID); if (sInstance != null) {
return sInstance;
}
if (DEBUG) {
Log.d(TAG, "Init the instance.");
}
sInstance = new MobileNetworkRepository(context);
return sInstance;
}
} }
public static MobileNetworkRepository createBySubId(Context context, private MobileNetworkRepository(Context context) {
MobileNetworkCallback mobileNetworkCallback, int subId) {
return new MobileNetworkRepository(context, mobileNetworkCallback, subId);
}
private MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback,
int subId) {
mSubId = subId;
mContext = context; mContext = context;
mMobileNetworkDatabase = MobileNetworkDatabase.getInstance(context); mMobileNetworkDatabase = MobileNetworkDatabase.getInstance(context);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED, mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
subId);
mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mCallback = mobileNetworkCallback;
mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao(); mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao();
mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao(); mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao();
mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao(); mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao();
@@ -138,6 +142,8 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED);
mFilter.addAction(ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); mFilter.addAction(ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED); mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED);
mDataSubscriptionChangedReceiver = new DataSubscriptionChangedReceiver();
mContext.registerReceiver(mDataSubscriptionChangedReceiver, mFilter);
} }
private class AirplaneModeObserver extends ContentObserver { private class AirplaneModeObserver extends ContentObserver {
@@ -157,56 +163,98 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
@Override @Override
public void onChange(boolean selfChange, Uri uri) { public void onChange(boolean selfChange, Uri uri) {
if (uri.equals(mAirplaneModeSettingUri)) { if (uri.equals(mAirplaneModeSettingUri)) {
mCallback.onAirplaneModeChanged(isAirplaneModeOn()); boolean isAirplaneModeOn = isAirplaneModeOn();
for (MobileNetworkCallback callback : sCallbacks) {
callback.onAirplaneModeChanged(isAirplaneModeOn);
}
} }
} }
} }
private final BroadcastReceiver mDataSubscriptionChangedReceiver = new BroadcastReceiver() { private class DataSubscriptionChangedReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
onSubscriptionsChanged(); onSubscriptionsChanged();
} }
}; }
public void addRegister(LifecycleOwner lifecycleOwner) { /**
* Register all callbacks and listener.
*
* @param lifecycleOwner The lifecycle owner.
* @param mobileNetworkCallback A callback to receive all MobileNetwork's changes.
* @param subId The subscription ID to register relevant changes and listener for specific
* subscription.
*/
public void addRegister(LifecycleOwner lifecycleOwner,
MobileNetworkCallback mobileNetworkCallback, int subId) {
sCallbacks.add(mobileNetworkCallback);
mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this);
mAirplaneModeObserver.register(mContext); mAirplaneModeObserver.register(mContext);
mContext.registerReceiver(mDataSubscriptionChangedReceiver, mFilter);
observeAllSubInfo(lifecycleOwner); observeAllSubInfo(lifecycleOwner);
observeAllUiccInfo(lifecycleOwner); observeAllUiccInfo(lifecycleOwner);
observeAllMobileNetworkInfo(lifecycleOwner); observeAllMobileNetworkInfo(lifecycleOwner);
if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
addRegisterBySubId(subId);
createTelephonyManagerBySubId(subId);
}
} }
private void addRegisterBySubId(int subId) { private void addRegisterBySubId(int subId) {
if (!mTelephonyCallbackMap.containsKey(subId) || !mTelephonyManagerMap.containsKey(subId)) { MobileDataContentObserver dataContentObserver = new MobileDataContentObserver(
PhoneCallStateTelephonyCallback new Handler(Looper.getMainLooper()));
telephonyCallback = new PhoneCallStateTelephonyCallback(); dataContentObserver.setOnMobileDataChangedListener(() -> {
mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), sExecutor.execute(() -> {
telephonyCallback); insertMobileNetworkInfo(mContext, subId,
mTelephonyCallbackMap.put(subId, telephonyCallback); getTelephonyManagerBySubId(mContext, subId));
mTelephonyManagerMap.put(subId, mTelephonyManager);
}
if (!mDataContentObserverMap.containsKey(subId)) {
MobileDataContentObserver dataContentObserver = new MobileDataContentObserver(
new Handler(Looper.getMainLooper()));
dataContentObserver.register(mContext, subId);
dataContentObserver.setOnMobileDataChangedListener(() -> {
sExecutor.execute(() -> {
insertMobileNetworkInfo(mContext, String.valueOf(subId));
});
}); });
mDataContentObserverMap.put(subId, dataContentObserver); });
dataContentObserver.register(mContext, subId);
mDataContentObserverMap.put(subId, dataContentObserver);
}
private void createTelephonyManagerBySubId(int subId) {
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
return;
} }
PhoneCallStateTelephonyCallback
telephonyCallback = new PhoneCallStateTelephonyCallback();
TelephonyManager telephonyManager = mContext.getSystemService(
TelephonyManager.class).createForSubscriptionId(subId);
telephonyManager.registerTelephonyCallback(mContext.getMainExecutor(),
telephonyCallback);
mTelephonyCallbackMap.put(subId, telephonyCallback);
mTelephonyManagerMap.put(subId, telephonyManager);
}
private TelephonyManager getTelephonyManagerBySubId(Context context, int subId) {
TelephonyManager telephonyManager = mTelephonyManagerMap.get(subId);
if (telephonyManager != null) {
return telephonyManager;
}
if (context != null) {
telephonyManager = context.getSystemService(TelephonyManager.class);
if (telephonyManager != null) {
telephonyManager = telephonyManager.createForSubscriptionId(subId);
} else if (DEBUG) {
Log.d(TAG, "Can not get TelephonyManager for subId " + subId);
}
}
return telephonyManager;
} }
private void removerRegisterBySubId(int subId) { private void removerRegisterBySubId(int subId) {
if (mTelephonyCallbackMap.containsKey(subId)) { if (mTelephonyCallbackMap.containsKey(subId)) {
TelephonyManager tm = mTelephonyManagerMap.get(subId); TelephonyManager telephonyManager = getTelephonyManagerBySubId(mContext, subId);
PhoneCallStateTelephonyCallback callback = mTelephonyCallbackMap.get(subId); if (telephonyManager != null) {
if (callback != null) { PhoneCallStateTelephonyCallback callback = mTelephonyCallbackMap.get(subId);
tm.unregisterTelephonyCallback(callback); if (callback != null) {
mTelephonyCallbackMap.remove(subId); telephonyManager.unregisterTelephonyCallback(callback);
mTelephonyCallbackMap.remove(subId);
}
} }
} }
if (mDataContentObserverMap.containsKey(subId)) { if (mDataContentObserverMap.containsKey(subId)) {
@@ -215,25 +263,43 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
} }
} }
public void removeRegister() { public void removeRegister(MobileNetworkCallback mobileNetworkCallback) {
mSubscriptionManager.removeOnSubscriptionsChangedListener(this); sCallbacks.remove(mobileNetworkCallback);
mAirplaneModeObserver.unRegister(mContext); if (sCallbacks.isEmpty()) {
if (mDataSubscriptionChangedReceiver != null) { mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
mContext.unregisterReceiver(mDataSubscriptionChangedReceiver); mAirplaneModeObserver.unRegister(mContext);
} if (mDataSubscriptionChangedReceiver != null) {
mDataContentObserverMap.forEach((id, observer) -> { mContext.unregisterReceiver(mDataSubscriptionChangedReceiver);
observer.unRegister(mContext); mDataSubscriptionChangedReceiver = null;
});
mDataContentObserverMap.clear();
mTelephonyManagerMap.forEach((id, manager) -> {
TelephonyCallback callback = mTelephonyCallbackMap.get(manager.getSubscriptionId());
if (callback != null) {
manager.unregisterTelephonyCallback(callback);
} }
}); mDataContentObserverMap.forEach((id, observer) -> {
mTelephonyCallbackMap.clear(); observer.unRegister(mContext);
mTelephonyManagerMap.clear(); });
mDataContentObserverMap.clear();
mTelephonyManagerMap.forEach((id, manager) -> {
TelephonyCallback callback = mTelephonyCallbackMap.get(id);
if (callback != null) {
manager.unregisterTelephonyCallback(callback);
}
});
mTelephonyCallbackMap.clear();
mTelephonyManagerMap.clear();
}
}
public void updateEntity() {
// Check the latest state after back to the UI.
if (sCacheSubscriptionInfoEntityMap != null || !sCacheSubscriptionInfoEntityMap.isEmpty()) {
sExecutor.execute(() -> {
onSubscriptionsChanged();
});
}
boolean isAirplaneModeOn = isAirplaneModeOn();
for (MobileNetworkCallback callback : sCallbacks) {
callback.onAirplaneModeChanged(isAirplaneModeOn);
}
} }
private void observeAllSubInfo(LifecycleOwner lifecycleOwner) { private void observeAllSubInfo(LifecycleOwner lifecycleOwner) {
@@ -284,18 +350,6 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
return mMobileNetworkInfoDao.queryMobileNetworkInfoBySubId(subId); return mMobileNetworkInfoDao.queryMobileNetworkInfoBySubId(subId);
} }
public int getSubInfosCount() {
return mSubscriptionInfoDao.count();
}
public int getUiccInfosCount() {
return mUiccInfoDao.count();
}
public int getMobileNetworkInfosCount() {
return mMobileNetworkInfoDao.count();
}
private void getUiccInfoBySubscriptionInfo(UiccSlotInfo[] uiccSlotInfos, private void getUiccInfoBySubscriptionInfo(UiccSlotInfo[] uiccSlotInfos,
SubscriptionInfo subInfo) { SubscriptionInfo subInfo) {
for (int i = 0; i < uiccSlotInfos.length; i++) { for (int i = 0; i < uiccSlotInfos.length; i++) {
@@ -317,7 +371,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
mPortIndex = portInfo.getPortIndex(); mPortIndex = portInfo.getPortIndex();
} else if (DEBUG) { } else if (DEBUG) {
Log.d(TAG, "Can not get port index and physicalSlotIndex for subId " Log.d(TAG, "Can not get port index and physicalSlotIndex for subId "
+ mSubId); + subInfo.getSubscriptionId());
} }
}); });
if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
@@ -334,70 +388,82 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
private void onAvailableSubInfoChanged( private void onAvailableSubInfoChanged(
List<SubscriptionInfoEntity> availableSubInfoEntityList) { List<SubscriptionInfoEntity> availableSubInfoEntityList) {
mAvailableSubInfoEntityList = availableSubInfoEntityList; mAvailableSubInfoEntityList = new ArrayList<>(availableSubInfoEntityList);
mActiveSubInfoEntityList = mAvailableSubInfoEntityList.stream()
.filter(SubscriptionInfoEntity::isActiveSubscription)
.filter(SubscriptionInfoEntity::isSubscriptionVisible)
.collect(Collectors.toList());
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "onAvailableSubInfoChanged, availableSubInfoEntityList = " Log.d(TAG, "onAvailableSubInfoChanged, availableSubInfoEntityList = "
+ availableSubInfoEntityList); + availableSubInfoEntityList);
} }
mCallback.onAvailableSubInfoChanged(availableSubInfoEntityList); for (MobileNetworkCallback callback : sCallbacks) {
callback.onAvailableSubInfoChanged(availableSubInfoEntityList);
}
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_SUB_INFO_IS_CHANGED, 0); SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_SUB_INFO_IS_CHANGED, 0);
setActiveSubInfoList(mActiveSubInfoEntityList); onActiveSubInfoListChanged(mAvailableSubInfoEntityList);
} }
private void setActiveSubInfoList(List<SubscriptionInfoEntity> activeSubInfoEntityList) { private void onActiveSubInfoListChanged(
List<SubscriptionInfoEntity> availableSubInfoEntityList) {
mActiveSubInfoEntityList = availableSubInfoEntityList.stream()
.filter(SubscriptionInfoEntity::isActiveSubscription)
.filter(SubscriptionInfoEntity::isSubscriptionVisible)
.collect(Collectors.toList());
if (DEBUG) { if (DEBUG) {
Log.d(TAG, Log.d(TAG, "onActiveSubInfoChanged, activeSubInfoEntityList = "
"onActiveSubInfoChanged, activeSubInfoEntityList = " + activeSubInfoEntityList); + mActiveSubInfoEntityList);
}
List<SubscriptionInfoEntity> activeSubInfoEntityList = new ArrayList<>(
mActiveSubInfoEntityList);
for (MobileNetworkCallback callback : sCallbacks) {
callback.onActiveSubInfoChanged(activeSubInfoEntityList);
} }
mCallback.onActiveSubInfoChanged(mActiveSubInfoEntityList);
} }
private void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) { private void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
mUiccInfoEntityList = uiccInfoEntityList; mUiccInfoEntityList = new ArrayList<>(uiccInfoEntityList);
mCallback.onAllUiccInfoChanged(uiccInfoEntityList); for (MobileNetworkCallback callback : sCallbacks) {
callback.onAllUiccInfoChanged(uiccInfoEntityList);
}
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_UICC_INFO_IS_CHANGED, 0); SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_UICC_INFO_IS_CHANGED, 0);
} }
private void onAllMobileNetworkInfoChanged( private void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) { List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList; mMobileNetworkInfoEntityList = new ArrayList<>(mobileNetworkInfoEntityList);
mCallback.onAllMobileNetworkInfoChanged(mobileNetworkInfoEntityList); for (MobileNetworkCallback callback : sCallbacks) {
callback.onAllMobileNetworkInfoChanged(mobileNetworkInfoEntityList);
}
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_MOBILE_NETWORK_INFO_IS_CHANGED, 0); SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_MOBILE_NETWORK_INFO_IS_CHANGED, 0);
} }
public void insertSubInfo(Context context, SubscriptionInfo info) { private void insertSubInfo(Context context, SubscriptionInfo info) {
int subId = info.getSubscriptionId();
createTelephonyManagerBySubId(subId);
TelephonyManager telephonyManager = getTelephonyManagerBySubId(context, subId);
SubscriptionInfoEntity subInfoEntity = SubscriptionInfoEntity subInfoEntity =
convertToSubscriptionInfoEntity(context, info); convertToSubscriptionInfoEntity(context, info, telephonyManager);
String subId = String.valueOf(mSubId);
if (subInfoEntity != null) { if (subInfoEntity != null) {
if (!sCacheSubscriptionInfoEntityMap.containsKey(subId) if (!sCacheSubscriptionInfoEntityMap.containsKey(subId)
|| (sCacheSubscriptionInfoEntityMap.get(subId) != null || (sCacheSubscriptionInfoEntityMap.get(subId) != null
&& !sCacheSubscriptionInfoEntityMap.get(subId).equals(subInfoEntity))) { && !sCacheSubscriptionInfoEntityMap.get(subId).equals(subInfoEntity))) {
sCacheSubscriptionInfoEntityMap.put(subId, subInfoEntity); sCacheSubscriptionInfoEntityMap.put(subId, subInfoEntity);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "convert subId " + subId + "to SubscriptionInfoEntity: " Log.d(TAG, "Convert subId " + subId + " to SubscriptionInfoEntity: "
+ subInfoEntity); + subInfoEntity);
} }
mMobileNetworkDatabase.insertSubsInfo(subInfoEntity); mMobileNetworkDatabase.insertSubsInfo(subInfoEntity);
addRegisterBySubId(mSubId);
insertUiccInfo(subId);
insertMobileNetworkInfo(context, subId);
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_SUB_INFO, mSubId); SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_SUB_INFO, subId);
} else if (DEBUG) { insertUiccInfo(subId, telephonyManager);
Log.d(TAG, "Can not insert subInfo, the entity is null"); insertMobileNetworkInfo(context, subId, telephonyManager);
} }
} else if (DEBUG) {
Log.d(TAG, "Can not insert subInfo, the entity is null");
} }
} }
public void deleteAllInfoBySubId(String subId) { private void deleteAllInfoBySubId(String subId) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "deleteAllInfoBySubId, subId = " + subId); Log.d(TAG, "deleteAllInfoBySubId, subId = " + subId);
} }
@@ -412,20 +478,23 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
removerRegisterBySubId(id); removerRegisterBySubId(id);
mSubscriptionInfoMap.remove(id); mSubscriptionInfoMap.remove(id);
mTelephonyManagerMap.remove(id); mTelephonyManagerMap.remove(id);
sCacheSubscriptionInfoEntityMap.remove(subId); sCacheSubscriptionInfoEntityMap.remove(id);
sCacheUiccInfoEntityMap.remove(subId); sCacheUiccInfoEntityMap.remove(id);
sCacheMobileNetworkInfoEntityMap.remove(subId); sCacheMobileNetworkInfoEntityMap.remove(id);
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_DELETE_DATA, id); SettingsEnums.ACTION_MOBILE_NETWORK_DB_DELETE_DATA, id);
} }
public SubscriptionInfoEntity convertToSubscriptionInfoEntity(Context context, private SubscriptionInfoEntity convertToSubscriptionInfoEntity(Context context,
SubscriptionInfo subInfo) { SubscriptionInfo subInfo, TelephonyManager telephonyManager) {
mSubId = subInfo.getSubscriptionId(); int subId = subInfo.getSubscriptionId();
mTelephonyManager = context.getSystemService( if (telephonyManager == null) {
TelephonyManager.class).createForSubscriptionId(mSubId); if (DEBUG) {
Log.d(TAG, "Can not get TelephonyManager for subId " + subId);
UiccSlotInfo[] uiccSlotInfos = mTelephonyManager.getUiccSlotsInfo(); }
return null;
}
UiccSlotInfo[] uiccSlotInfos = telephonyManager.getUiccSlotsInfo();
if (uiccSlotInfos == null || uiccSlotInfos.length == 0) { if (uiccSlotInfos == null || uiccSlotInfos.length == 0) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "uiccSlotInfos = null or empty"); Log.d(TAG, "uiccSlotInfos = null or empty");
@@ -435,10 +504,10 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
getUiccInfoBySubscriptionInfo(uiccSlotInfos, subInfo); getUiccInfoBySubscriptionInfo(uiccSlotInfos, subInfo);
SubscriptionInfo firstRemovableSubInfo = SubscriptionUtil.getFirstRemovableSubscription( SubscriptionInfo firstRemovableSubInfo = SubscriptionUtil.getFirstRemovableSubscription(
context); context);
if(DEBUG){ if (DEBUG) {
Log.d(TAG, "convert subscriptionInfo to entity for subId = " + mSubId); Log.d(TAG, "convert subscriptionInfo to entity for subId = " + subId);
} }
return new SubscriptionInfoEntity(String.valueOf(mSubId), return new SubscriptionInfoEntity(String.valueOf(subId),
subInfo.getSimSlotIndex(), subInfo.getSimSlotIndex(),
subInfo.getCarrierId(), subInfo.getDisplayName().toString(), subInfo.getCarrierId(), subInfo.getDisplayName().toString(),
subInfo.getCarrierName() != null ? subInfo.getCarrierName().toString() : "", subInfo.getCarrierName() != null ? subInfo.getCarrierName().toString() : "",
@@ -451,23 +520,23 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
SubscriptionUtil.isSubscriptionVisible(mSubscriptionManager, context, subInfo), SubscriptionUtil.isSubscriptionVisible(mSubscriptionManager, context, subInfo),
SubscriptionUtil.getFormattedPhoneNumber(context, subInfo), SubscriptionUtil.getFormattedPhoneNumber(context, subInfo),
firstRemovableSubInfo == null ? false firstRemovableSubInfo == null ? false
: firstRemovableSubInfo.getSubscriptionId() == mSubId, : firstRemovableSubInfo.getSubscriptionId() == subId,
String.valueOf(SubscriptionUtil.getDefaultSimConfig(context, mSubId)), String.valueOf(SubscriptionUtil.getDefaultSimConfig(context, subId)),
SubscriptionUtil.isDefaultSubscription(context, mSubId), SubscriptionUtil.isDefaultSubscription(context, subId),
mSubscriptionManager.isValidSubscriptionId(mSubId), mSubscriptionManager.isValidSubscriptionId(subId),
mSubscriptionManager.isUsableSubscriptionId(mSubId), mSubscriptionManager.isUsableSubscriptionId(subId),
mSubscriptionManager.isActiveSubscriptionId(mSubId), mSubscriptionManager.isActiveSubscriptionId(subId),
true /*availableSubInfo*/, true /*availableSubInfo*/,
mSubscriptionManager.getDefaultVoiceSubscriptionId() == mSubId, mSubscriptionManager.getDefaultVoiceSubscriptionId() == subId,
mSubscriptionManager.getDefaultSmsSubscriptionId() == mSubId, mSubscriptionManager.getDefaultSmsSubscriptionId() == subId,
mSubscriptionManager.getDefaultDataSubscriptionId() == mSubId, mSubscriptionManager.getDefaultDataSubscriptionId() == subId,
mSubscriptionManager.getDefaultSubscriptionId() == mSubId, mSubscriptionManager.getDefaultSubscriptionId() == subId,
mSubscriptionManager.getActiveDataSubscriptionId() == mSubId); mSubscriptionManager.getActiveDataSubscriptionId() == subId);
} }
} }
public void insertUiccInfo(String subId) { private void insertUiccInfo(int subId, TelephonyManager telephonyManager) {
UiccInfoEntity uiccInfoEntity = convertToUiccInfoEntity(); UiccInfoEntity uiccInfoEntity = convertToUiccInfoEntity(subId, telephonyManager);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "uiccInfoEntity = " + uiccInfoEntity); Log.d(TAG, "uiccInfoEntity = " + uiccInfoEntity);
} }
@@ -476,51 +545,76 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
sCacheUiccInfoEntityMap.put(subId, uiccInfoEntity); sCacheUiccInfoEntityMap.put(subId, uiccInfoEntity);
mMobileNetworkDatabase.insertUiccInfo(uiccInfoEntity); mMobileNetworkDatabase.insertUiccInfo(uiccInfoEntity);
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_UICC_INFO, SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_UICC_INFO, subId);
Integer.parseInt(subId));
} }
} }
public void insertMobileNetworkInfo(Context context, String subId) { private void insertMobileNetworkInfo(Context context, int subId,
MobileNetworkInfoEntity mobileNetworkInfoEntity = convertToMobileNetworkInfoEntity(context); TelephonyManager telephonyManager) {
MobileNetworkInfoEntity mobileNetworkInfoEntity = convertToMobileNetworkInfoEntity(context,
subId, telephonyManager);
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "mobileNetworkInfoEntity = " + mobileNetworkInfoEntity); Log.d(TAG, "insertMobileNetworkInfo, mobileNetworkInfoEntity = "
+ mobileNetworkInfoEntity);
} }
if (mobileNetworkInfoEntity == null) {
return;
}
if (!sCacheMobileNetworkInfoEntityMap.containsKey(subId) if (!sCacheMobileNetworkInfoEntityMap.containsKey(subId)
|| !sCacheMobileNetworkInfoEntityMap.get(subId).equals(mobileNetworkInfoEntity)) { || !sCacheMobileNetworkInfoEntityMap.get(subId).equals(mobileNetworkInfoEntity)) {
sCacheMobileNetworkInfoEntityMap.put(subId, mobileNetworkInfoEntity); sCacheMobileNetworkInfoEntityMap.put(subId, mobileNetworkInfoEntity);
mMobileNetworkDatabase.insertMobileNetworkInfo(mobileNetworkInfoEntity); mMobileNetworkDatabase.insertMobileNetworkInfo(mobileNetworkInfoEntity);
mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_MOBILE_NETWORK_INFO, SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_MOBILE_NETWORK_INFO, subId);
Integer.parseInt(subId));
} }
} }
public MobileNetworkInfoEntity convertToMobileNetworkInfoEntity(Context context) { private MobileNetworkInfoEntity convertToMobileNetworkInfoEntity(Context context, int subId,
return new MobileNetworkInfoEntity(String.valueOf(mSubId), TelephonyManager telephonyManager) {
MobileNetworkUtils.isContactDiscoveryEnabled(context, mSubId), boolean isDataEnabled = false;
MobileNetworkUtils.isContactDiscoveryVisible(context, mSubId), boolean isDataRoamingEnabled = false;
mTelephonyManager.isDataEnabled(), if (telephonyManager != null) {
MobileNetworkUtils.isCdmaOptions(context, mSubId), isDataEnabled = telephonyManager.isDataEnabled();
MobileNetworkUtils.isGsmOptions(context, mSubId), isDataRoamingEnabled = telephonyManager.isDataRoamingEnabled();
MobileNetworkUtils.isWorldMode(context, mSubId), } else if (DEBUG) {
MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, mSubId), Log.d(TAG, "TelephonyManager is null, subId = " + subId);
MobileNetworkUtils.isTdscdmaSupported(context, mSubId), }
return new MobileNetworkInfoEntity(String.valueOf(subId),
MobileNetworkUtils.isContactDiscoveryEnabled(context, subId),
MobileNetworkUtils.isContactDiscoveryVisible(context, subId),
isDataEnabled,
MobileNetworkUtils.isCdmaOptions(context, subId),
MobileNetworkUtils.isGsmOptions(context, subId),
MobileNetworkUtils.isWorldMode(context, subId),
MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, subId),
MobileNetworkUtils.isTdscdmaSupported(context, subId),
MobileNetworkUtils.activeNetworkIsCellular(context), MobileNetworkUtils.activeNetworkIsCellular(context),
SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager), SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager),
mTelephonyManager.isDataRoamingEnabled() isDataRoamingEnabled
); );
} }
private UiccInfoEntity convertToUiccInfoEntity() { private UiccInfoEntity convertToUiccInfoEntity(int subId, TelephonyManager telephonyManager) {
return new UiccInfoEntity(String.valueOf(mSubId), String.valueOf(mPhysicalSlotIndex), return new UiccInfoEntity(String.valueOf(subId), String.valueOf(mPhysicalSlotIndex),
mLogicalSlotIndex, mCardId, mIsEuicc, isMultipleEnabledProfilesSupported(), mLogicalSlotIndex, mCardId, mIsEuicc,
mCardState, mIsRemovable, mIsActive, mPortIndex isMultipleEnabledProfilesSupported(telephonyManager), mCardState, mIsRemovable,
mIsActive, mPortIndex
); );
} }
private boolean isMultipleEnabledProfilesSupported() { private boolean isMultipleEnabledProfilesSupported(TelephonyManager telephonyManager) {
List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo(); if (telephonyManager == null) {
if (DEBUG) {
Log.d(TAG, "TelephonyManager is null");
}
return false;
}
List<UiccCardInfo> cardInfos = telephonyManager.getUiccCardsInfo();
if (cardInfos == null) { if (cardInfos == null) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "UICC card info list is empty."); Log.d(TAG, "UICC card info list is empty.");
@@ -574,7 +668,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
// the database, if the subInfo is not existed in the new list, delete it // the database, if the subInfo is not existed in the new list, delete it
// from the database. // from the database.
for (SubscriptionInfoEntity info : availableInfoArray) { for (SubscriptionInfoEntity info : availableInfoArray) {
if (sCacheSubscriptionInfoEntityMap.containsKey(info.subId)) { if (sCacheSubscriptionInfoEntityMap.containsKey(info.getSubId())) {
deleteAllInfoBySubId(info.subId); deleteAllInfoBySubId(info.subId);
} }
} }
@@ -593,7 +687,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
} }
continue; continue;
} }
mSubscriptionInfoMap.put(mSubId, subInfo); mSubscriptionInfoMap.put(subInfo.getSubscriptionId(), subInfo);
insertSubInfo(mContext, subInfo); insertSubInfo(mContext, subInfo);
} }
} }
@@ -610,7 +704,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions
@Override @Override
public void onCallStateChanged(int state) { public void onCallStateChanged(int state) {
mCallback.onCallStateChanged(state); for (MobileNetworkCallback callback : sCallbacks) {
callback.onCallStateChanged(state);
}
} }
} }

View File

@@ -22,6 +22,7 @@ import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.UserManager; import android.os.UserManager;
import android.telephony.SubscriptionManager;
import android.telephony.euicc.EuiccManager; import android.telephony.euicc.EuiccManager;
import android.util.Log; import android.util.Log;
@@ -87,7 +88,7 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
mUserManager = context.getSystemService(UserManager.class); mUserManager = context.getSystemService(UserManager.class);
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mIsAirplaneModeOn = mMobileNetworkRepository.isAirplaneModeOn(); mIsAirplaneModeOn = mMobileNetworkRepository.isAirplaneModeOn();
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
@@ -96,13 +97,14 @@ public class MobileNetworkSummaryController extends AbstractPreferenceController
@OnLifecycleEvent(ON_RESUME) @OnLifecycleEvent(ON_RESUME)
public void onResume() { public void onResume() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
update(); SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(ON_PAUSE) @OnLifecycleEvent(ON_PAUSE)
public void onPause() { public void onPause() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override

View File

@@ -21,6 +21,7 @@ import static androidx.lifecycle.Lifecycle.Event;
import android.content.Context; import android.content.Context;
import android.os.UserManager; import android.os.UserManager;
import android.telephony.ServiceState; import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@@ -71,7 +72,7 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl
mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_RTL; == View.LAYOUT_DIRECTION_RTL;
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
} }
@@ -79,13 +80,14 @@ public class NetworkProviderCallsSmsController extends AbstractPreferenceControl
@OnLifecycleEvent(Event.ON_RESUME) @OnLifecycleEvent(Event.ON_RESUME)
public void onResume() { public void onResume() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
update(); SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(Event.ON_PAUSE) @OnLifecycleEvent(Event.ON_PAUSE)
public void onPause() { public void onPause() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override

View File

@@ -65,19 +65,20 @@ public class NetworkProviderSimListController extends AbstractPreferenceControll
mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mPreferences = new ArrayMap<>(); mPreferences = new ArrayMap<>();
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
lifecycle.addObserver(this); lifecycle.addObserver(this);
} }
@OnLifecycleEvent(ON_RESUME) @OnLifecycleEvent(ON_RESUME)
public void onResume() { public void onResume() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
update(); SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(ON_PAUSE) @OnLifecycleEvent(ON_PAUSE)
public void onPause() { public void onPause() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override

View File

@@ -52,7 +52,7 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo
LifecycleOwner lifecycleOwner, int subId) { LifecycleOwner lifecycleOwner, int subId) {
super(context, key); super(context, key);
mSubId = subId; mSubId = subId;
mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
@@ -66,12 +66,13 @@ public class ConvertToEsimPreferenceController extends TelephonyBasePreferenceCo
@OnLifecycleEvent(ON_START) @OnLifecycleEvent(ON_START)
public void onStart() { public void onStart() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this, mSubId);
mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(ON_STOP) @OnLifecycleEvent(ON_STOP)
public void onStop() { public void onStop() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override

View File

@@ -75,7 +75,7 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
mManager = context.getSystemService(SubscriptionManager.class); mManager = context.getSystemService(SubscriptionManager.class);
mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection() mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
== View.LAYOUT_DIRECTION_RTL; == View.LAYOUT_DIRECTION_RTL;
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
@@ -104,13 +104,13 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
@OnLifecycleEvent(ON_RESUME) @OnLifecycleEvent(ON_RESUME)
public void onResume() { public void onResume() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this, getDefaultSubscriptionId());
updateEntries(); mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(ON_PAUSE) @OnLifecycleEvent(ON_PAUSE)
public void onPause() { public void onPause() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override
@@ -303,6 +303,4 @@ public abstract class DefaultSubscriptionController extends TelephonyBasePrefere
updateEntries(); updateEntries();
refreshSummary(mPreference); refreshSummary(mPreference);
} }
} }

View File

@@ -58,7 +58,6 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon
private SwitchPreference mPreference; private SwitchPreference mPreference;
private TelephonyManager mTelephonyManager; private TelephonyManager mTelephonyManager;
private SubscriptionManager mSubscriptionManager; private SubscriptionManager mSubscriptionManager;
private MobileDataContentObserver mDataContentObserver;
private FragmentManager mFragmentManager; private FragmentManager mFragmentManager;
@VisibleForTesting @VisibleForTesting
int mDialogType; int mDialogType;
@@ -79,9 +78,7 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon
super(context, key); super(context, key);
mSubId = subId; mSubId = subId;
mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mDataContentObserver = new MobileDataContentObserver(new Handler(Looper.getMainLooper())); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mDataContentObserver.setOnMobileDataChangedListener(() -> updateState(mPreference));
mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId);
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
@@ -103,12 +100,13 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon
@OnLifecycleEvent(ON_START) @OnLifecycleEvent(ON_START)
public void onStart() { public void onStart() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this, mSubId);
mMobileNetworkRepository.updateEntity();
} }
@OnLifecycleEvent(ON_STOP) @OnLifecycleEvent(ON_STOP)
public void onStop() { public void onStop() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@Override @Override

View File

@@ -158,7 +158,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
MobileNetworkUtils.getSearchableSubscriptionId(context)); MobileNetworkUtils.getSearchableSubscriptionId(context));
Log.d(LOG_TAG, "display subId from getArguments(): " + mSubId); Log.d(LOG_TAG, "display subId from getArguments(): " + mSubId);
} }
mMobileNetworkRepository = MobileNetworkRepository.create(context, this); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mExecutor.execute(() -> { mExecutor.execute(() -> {
mSubscriptionInfoEntity = mMobileNetworkRepository.getSubInfoById( mSubscriptionInfoEntity = mMobileNetworkRepository.getSubInfoById(
String.valueOf(mSubId)); String.valueOf(mSubId));
@@ -177,6 +177,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
new SmsDefaultSubscriptionController(context, KEY_SMS_PREF, getSettingsLifecycle(), new SmsDefaultSubscriptionController(context, KEY_SMS_PREF, getSettingsLifecycle(),
this), this),
new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF, new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF,
getSettingsLifecycle(), this, mSubId),
new ConvertToEsimPreferenceController(context, KEY_CONVERT_TO_ESIM_PREF,
getSettingsLifecycle(), this, mSubId)); getSettingsLifecycle(), this, mSubId));
} }
@@ -322,7 +324,8 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mMobileNetworkRepository.addRegister(this); mMobileNetworkRepository.addRegister(this, this, mSubId);
mMobileNetworkRepository.updateEntity();
// TODO: remove log after fixing b/182326102 // TODO: remove log after fixing b/182326102
Log.d(LOG_TAG, "onResume() subId=" + mSubId); Log.d(LOG_TAG, "onResume() subId=" + mSubId);
} }
@@ -350,7 +353,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
} }
@VisibleForTesting @VisibleForTesting
@@ -505,7 +508,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
break; break;
} else if (entity.isDefaultSubscriptionSelection) { } else if (entity.isDefaultSubscriptionSelection) {
mSubscriptionInfoEntity = entity; mSubscriptionInfoEntity = entity;
Log.d(LOG_TAG, "Set subInfo to the default subInfo."); Log.d(LOG_TAG, "Set subInfo to default subInfo.");
} }
} }
onSubscriptionDetailChanged(); onSubscriptionDetailChanged();

View File

@@ -949,7 +949,12 @@ public class MobileNetworkUtils {
boolean isWifiCallingEnabled; boolean isWifiCallingEnabled;
if (phoneAccountHandle != null) { if (phoneAccountHandle != null) {
final Intent intent = buildPhoneAccountConfigureIntent(context, phoneAccountHandle); final Intent intent = buildPhoneAccountConfigureIntent(context, phoneAccountHandle);
isWifiCallingEnabled = intent != null; if (intent == null) {
Log.d(TAG, "Can not get phoneAccount configure intent.");
isWifiCallingEnabled = false;
} else {
isWifiCallingEnabled = true;
}
} else { } else {
if (queryImsState == null) { if (queryImsState == null) {
queryImsState = new WifiCallingQueryImsState(context, subId); queryImsState = new WifiCallingQueryImsState(context, subId);
@@ -959,7 +964,6 @@ public class MobileNetworkUtils {
return isWifiCallingEnabled; return isWifiCallingEnabled;
} }
/** /**
* Returns preferred status of Calls & SMS separately when Provider Model is enabled. * Returns preferred status of Calls & SMS separately when Provider Model is enabled.
*/ */

View File

@@ -314,29 +314,13 @@ public class NetworkProviderWifiCallingGroup extends
@VisibleForTesting @VisibleForTesting
protected boolean shouldShowWifiCallingForSub(int subId) { protected boolean shouldShowWifiCallingForSub(int subId) {
if (SubscriptionManager.isValidSubscriptionId(subId) if (SubscriptionManager.isValidSubscriptionId(subId)
&& MobileNetworkUtils.isWifiCallingEnabled( && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId, queryImsState(subId),
mContext, subId, queryImsState(subId), null)) {
getPhoneAccountHandleForSubscriptionId(subId))
&& isWifiCallingAvailableForCarrier(subId)) {
return true; return true;
} }
return false; return false;
} }
private boolean isWifiCallingAvailableForCarrier(int subId) {
boolean isWifiCallingAvailableForCarrier = false;
if (mCarrierConfigManager != null) {
final PersistableBundle carrierConfig =
mCarrierConfigManager.getConfigForSubId(subId);
if (carrierConfig != null) {
isWifiCallingAvailableForCarrier = carrierConfig.getBoolean(
CarrierConfigManager.KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL);
}
}
Log.d(TAG, "isWifiCallingAvailableForCarrier:" + isWifiCallingAvailableForCarrier);
return isWifiCallingAvailableForCarrier;
}
@Override @Override
public String getPreferenceKey() { public String getPreferenceKey() {
return KEY_PREFERENCE_WIFICALLING_GROUP; return KEY_PREFERENCE_WIFICALLING_GROUP;

View File

@@ -81,7 +81,7 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
super(context, key); super(context, key);
mSubId = subId; mSubId = subId;
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId); mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
mLifecycleOwner = lifecycleOwner; mLifecycleOwner = lifecycleOwner;
if (lifecycle != null) { if (lifecycle != null) {
lifecycle.addObserver(this); lifecycle.addObserver(this);
@@ -100,7 +100,8 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@OnLifecycleEvent(ON_START) @OnLifecycleEvent(ON_START)
public void onStart() { public void onStart() {
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, this, mSubId);
mMobileNetworkRepository.updateEntity();
if (mListener == null) { if (mListener == null) {
mListener = new GlobalSettingsChangeListener(mContext, mListener = new GlobalSettingsChangeListener(mContext,
Settings.Global.DATA_ROAMING) { Settings.Global.DATA_ROAMING) {
@@ -126,7 +127,7 @@ public class RoamingPreferenceController extends TelephonyTogglePreferenceContro
@OnLifecycleEvent(ON_STOP) @OnLifecycleEvent(ON_STOP)
public void onStop() { public void onStop() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(this);
stopMonitor(); stopMonitor();
stopMonitorSubIdSpecific(); stopMonitorSubIdSpecific();
} }

View File

@@ -25,7 +25,6 @@ import android.provider.Settings;
import android.telecom.PhoneAccountHandle; import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager; import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback; import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;

View File

@@ -267,7 +267,7 @@ public class AutoSelectPreferenceController extends TelephonyTogglePreferenceCon
private void queryNetworkSelectionMode(String tag) { private void queryNetworkSelectionMode(String tag) {
mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode(); mCacheOfModeStatus = mTelephonyManager.getNetworkSelectionMode();
Log.d(LOG_TAG, tag + ": query commend done. mCacheOfModeStatus: " + mCacheOfModeStatus); Log.d(LOG_TAG, tag + ": query command done. mCacheOfModeStatus: " + mCacheOfModeStatus);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -99,6 +99,7 @@ public class ConversationNotificationSettings extends NotificationSettings {
mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(), mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(),
mBackend, false /* isAppPage */, null /* dependentFieldListener */)); mBackend, false /* isAppPage */, null /* dependentFieldListener */));
mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend)); mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend));
mControllers.add(new ConversationPromotePreferenceController(context, this, mBackend));
mControllers.add(new BubbleCategoryPreferenceController(context)); mControllers.add(new BubbleCategoryPreferenceController(context));
mControllers.add(new BubbleLinkPreferenceController(context)); mControllers.add(new BubbleLinkPreferenceController(context));
return new ArrayList<>(mControllers); return new ArrayList<>(mControllers);

View File

@@ -16,17 +16,25 @@
package com.android.settings.spa.app.appinfo package com.android.settings.spa.app.appinfo
import android.app.AppOpsManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.UserManager import android.os.UserManager
import android.widget.Toast
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState import androidx.compose.runtime.produceState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import com.android.settings.R import com.android.settings.R
import com.android.settings.Utils import com.android.settings.Utils
import com.android.settings.applications.appinfo.AppInfoDashboardFragment
import com.android.settingslib.spa.widget.scaffold.MoreOptionsAction import com.android.settingslib.spa.widget.scaffold.MoreOptionsAction
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.framework.common.userManager import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
@@ -35,6 +43,8 @@ import com.android.settingslib.spaprivileged.model.app.userId
import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
import com.android.settingslib.spaprivileged.template.scaffold.RestrictedMenuItem import com.android.settingslib.spaprivileged.template.scaffold.RestrictedMenuItem
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@Composable @Composable
@@ -44,13 +54,11 @@ fun AppInfoSettingsMoreOptions(
packageManagers: IPackageManagers = PackageManagers, packageManagers: IPackageManagers = PackageManagers,
) { ) {
val state = app.produceState(packageManagers).value ?: return val state = app.produceState(packageManagers).value ?: return
when { var restrictedSettingsAllowed by rememberSaveable { mutableStateOf(false) }
// We don't allow uninstalling update for DO/PO if it's a system app, because it will clear if (!state.shownUninstallUpdates &&
// data on all users. We also don't allow uninstalling for all users if it's DO/PO for any !state.shownUninstallForAllUsers &&
// user. !(state.shouldShowAccessRestrictedSettings && !restrictedSettingsAllowed)
state.isProfileOrDeviceOwner -> return ) return
!state.shownUninstallUpdates && !state.shownUninstallForAllUsers -> return
}
MoreOptionsAction { MoreOptionsAction {
val restrictions = val restrictions =
Restrictions(userId = app.userId, keys = listOf(UserManager.DISALLOW_APPS_CONTROL)) Restrictions(userId = app.userId, keys = listOf(UserManager.DISALLOW_APPS_CONTROL))
@@ -70,13 +78,37 @@ fun AppInfoSettingsMoreOptions(
packageInfoPresenter.startUninstallActivity(forAllUsers = true) packageInfoPresenter.startUninstallActivity(forAllUsers = true)
} }
} }
if (state.shouldShowAccessRestrictedSettings && !restrictedSettingsAllowed) {
MenuItem(text = stringResource(R.string.app_restricted_settings_lockscreen_title)) {
app.allowRestrictedSettings(packageInfoPresenter.context) {
restrictedSettingsAllowed = true
}
}
}
}
}
private fun ApplicationInfo.allowRestrictedSettings(context: Context, onSuccess: () -> Unit) {
AppInfoDashboardFragment.showLockScreen(context) {
context.appOpsManager.setMode(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
uid,
packageName,
AppOpsManager.MODE_ALLOWED,
)
onSuccess()
val toastString = context.getString(
R.string.toast_allows_restricted_settings_successfully,
loadLabel(context.packageManager),
)
Toast.makeText(context, toastString, Toast.LENGTH_LONG).show()
} }
} }
private data class AppInfoSettingsMoreOptionsState( private data class AppInfoSettingsMoreOptionsState(
val isProfileOrDeviceOwner: Boolean,
val shownUninstallUpdates: Boolean, val shownUninstallUpdates: Boolean,
val shownUninstallForAllUsers: Boolean, val shownUninstallForAllUsers: Boolean,
val shouldShowAccessRestrictedSettings: Boolean,
) )
@Composable @Composable
@@ -86,20 +118,40 @@ private fun ApplicationInfo.produceState(
val context = LocalContext.current val context = LocalContext.current
return produceState<AppInfoSettingsMoreOptionsState?>(initialValue = null, this) { return produceState<AppInfoSettingsMoreOptionsState?>(initialValue = null, this) {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
value = AppInfoSettingsMoreOptionsState( value = getMoreOptionsState(context, packageManagers)
isProfileOrDeviceOwner = Utils.isProfileOrDeviceOwner(
context.userManager, context.devicePolicyManager, packageName
),
shownUninstallUpdates = isShowUninstallUpdates(context),
shownUninstallForAllUsers = isShowUninstallForAllUsers(
userManager = context.userManager,
packageManagers = packageManagers,
),
)
} }
} }
} }
private suspend fun ApplicationInfo.getMoreOptionsState(
context: Context,
packageManagers: IPackageManagers,
) = coroutineScope {
val shownUninstallUpdatesDeferred = async {
isShowUninstallUpdates(context)
}
val shownUninstallForAllUsersDeferred = async {
isShowUninstallForAllUsers(
userManager = context.userManager,
packageManagers = packageManagers,
)
}
val shouldShowAccessRestrictedSettingsDeferred = async {
shouldShowAccessRestrictedSettings(context.appOpsManager)
}
val isProfileOrDeviceOwner =
Utils.isProfileOrDeviceOwner(context.userManager, context.devicePolicyManager, packageName)
AppInfoSettingsMoreOptionsState(
// We don't allow uninstalling update for DO/PO if it's a system app, because it will clear
// data on all users.
shownUninstallUpdates = !isProfileOrDeviceOwner && shownUninstallUpdatesDeferred.await(),
// We also don't allow uninstalling for all users if it's DO/PO for any user.
shownUninstallForAllUsers =
!isProfileOrDeviceOwner && shownUninstallForAllUsersDeferred.await(),
shouldShowAccessRestrictedSettings = shouldShowAccessRestrictedSettingsDeferred.await(),
)
}
private fun ApplicationInfo.isShowUninstallUpdates(context: Context): Boolean = private fun ApplicationInfo.isShowUninstallUpdates(context: Context): Boolean =
isUpdatedSystemApp && context.userManager.isUserAdmin(userId) && isUpdatedSystemApp && context.userManager.isUserAdmin(userId) &&
!context.resources.getBoolean(R.bool.config_disable_uninstall_update) !context.resources.getBoolean(R.bool.config_disable_uninstall_update)
@@ -116,3 +168,8 @@ private fun ApplicationInfo.isOtherUserHasInstallPackage(
): Boolean = userManager.aliveUsers ): Boolean = userManager.aliveUsers
.filter { it.id != userId } .filter { it.id != userId }
.any { packageManagers.isPackageInstalledAsUser(packageName, it.id) } .any { packageManagers.isPackageInstalledAsUser(packageName, it.id) }
private fun ApplicationInfo.shouldShowAccessRestrictedSettings(appOpsManager: AppOpsManager) =
appOpsManager.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, uid, packageName, null, null
) == AppOpsManager.MODE_IGNORED

View File

@@ -257,7 +257,8 @@ public class WifiCallingSettings extends SettingsPreferenceFragment
for (SubscriptionInfo subInfo : subInfoList) { for (SubscriptionInfo subInfo : subInfoList) {
int subId = subInfo.getSubscriptionId(); int subId = subInfo.getSubscriptionId();
try { try {
if (queryImsState(subId).isWifiCallingProvisioned()) { if (MobileNetworkUtils.isWifiCallingEnabled(getContext(), subId,
queryImsState(subId), null)) {
selectedList.add(subInfo); selectedList.add(subInfo);
} }
} catch (Exception exception) {} } catch (Exception exception) {}

View File

@@ -95,10 +95,11 @@ public class MobileNetworkSummaryControllerTest {
doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class); doReturn(mSubscriptionManager).when(mContext).getSystemService(SubscriptionManager.class);
doReturn(mEuiccManager).when(mContext).getSystemService(EuiccManager.class); doReturn(mEuiccManager).when(mContext).getSystemService(EuiccManager.class);
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class); doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
mMobileNetworkRepository = MobileNetworkRepository.create(mContext, mMobileNetworkCallback); mMobileNetworkRepository = MobileNetworkRepository.getInstance(mContext);
mLifecycleOwner = () -> mLifecycle; mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner); mLifecycle = new Lifecycle(mLifecycleOwner);
mMobileNetworkRepository.addRegister(mLifecycleOwner); mMobileNetworkRepository.addRegister(mLifecycleOwner, mMobileNetworkCallback,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
when(mTelephonyManager.getNetworkCountryIso()).thenReturn(""); when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true); when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true);
@@ -114,7 +115,7 @@ public class MobileNetworkSummaryControllerTest {
@After @After
public void tearDown() { public void tearDown() {
mMobileNetworkRepository.removeRegister(); mMobileNetworkRepository.removeRegister(mMobileNetworkCallback);
SubscriptionUtil.setActiveSubscriptionsForTesting(null); SubscriptionUtil.setActiveSubscriptionsForTesting(null);
SubscriptionUtil.setAvailableSubscriptionsForTesting(null); SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
} }

View File

@@ -19,6 +19,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
package="com.android.settings.tests.spa_unit"> package="com.android.settings.tests.spa_unit">
<uses-permission android:name="android.permission.MANAGE_APPOPS" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
<application android:debuggable="true"> <application android:debuggable="true">

View File

@@ -16,6 +16,8 @@
package com.android.settings.spa.app.appinfo package com.android.settings.spa.app.appinfo
import android.app.AppOpsManager
import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
@@ -27,6 +29,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.test.assertIsNotDisplayed import androidx.compose.ui.test.assertIsNotDisplayed
import androidx.compose.ui.test.hasText import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performClick
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
@@ -36,6 +39,7 @@ import com.android.settings.R
import com.android.settings.Utils import com.android.settings.Utils
import com.android.settingslib.spa.testutils.delay import com.android.settingslib.spa.testutils.delay
import com.android.settingslib.spa.testutils.waitUntilExists import com.android.settingslib.spa.testutils.waitUntilExists
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.framework.common.userManager import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
@@ -46,6 +50,7 @@ import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoSession import org.mockito.MockitoSession
import org.mockito.Spy import org.mockito.Spy
import org.mockito.quality.Strictness import org.mockito.quality.Strictness
@@ -73,6 +78,12 @@ class AppInfoSettingsMoreOptionsTest {
@Mock @Mock
private lateinit var devicePolicyManager: DevicePolicyManager private lateinit var devicePolicyManager: DevicePolicyManager
@Mock
private lateinit var appOpsManager: AppOpsManager
@Mock
private lateinit var keyguardManager: KeyguardManager
@Spy @Spy
private var resources = context.resources private var resources = context.resources
@@ -90,6 +101,9 @@ class AppInfoSettingsMoreOptionsTest {
whenever(context.packageManager).thenReturn(packageManager) whenever(context.packageManager).thenReturn(packageManager)
whenever(context.userManager).thenReturn(userManager) whenever(context.userManager).thenReturn(userManager)
whenever(context.devicePolicyManager).thenReturn(devicePolicyManager) whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
whenever(context.appOpsManager).thenReturn(appOpsManager)
whenever(context.getSystemService(KeyguardManager::class.java)).thenReturn(keyguardManager)
whenever(keyguardManager.isKeyguardSecure).thenReturn(false)
whenever(Utils.isProfileOrDeviceOwner(userManager, devicePolicyManager, PACKAGE_NAME)) whenever(Utils.isProfileOrDeviceOwner(userManager, devicePolicyManager, PACKAGE_NAME))
.thenReturn(false) .thenReturn(false)
} }
@@ -143,6 +157,35 @@ class AppInfoSettingsMoreOptionsTest {
) )
} }
@Test
fun shouldShowAccessRestrictedSettings() {
whenever(
appOpsManager.noteOpNoThrow(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS, UID, PACKAGE_NAME, null, null
)
).thenReturn(AppOpsManager.MODE_IGNORED)
val app = ApplicationInfo().apply {
packageName = PACKAGE_NAME
uid = UID
}
setContent(app)
composeTestRule.onRoot().performClick()
composeTestRule.waitUntilExists(
hasText(context.getString(R.string.app_restricted_settings_lockscreen_title))
)
composeTestRule
.onNodeWithText(context.getString(R.string.app_restricted_settings_lockscreen_title))
.performClick()
verify(appOpsManager).setMode(
AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
UID,
PACKAGE_NAME,
AppOpsManager.MODE_ALLOWED,
)
}
private fun setContent(app: ApplicationInfo) { private fun setContent(app: ApplicationInfo) {
composeTestRule.setContent { composeTestRule.setContent {
CompositionLocalProvider(LocalContext provides context) { CompositionLocalProvider(LocalContext provides context) {

View File

@@ -75,7 +75,7 @@ public class CredentialManagerPreferenceControllerTest {
mScreen.addPreference(mCredentialsPreferenceCategory); mScreen.addPreference(mCredentialsPreferenceCategory);
} }
@Test /*@Test
// Tests that getAvailabilityStatus() does not throw an exception if it's called before the // Tests that getAvailabilityStatus() does not throw an exception if it's called before the
// Controller is initialized (this can happen during indexing). // Controller is initialized (this can happen during indexing).
public void getAvailabilityStatus_withoutInit_returnsUnavailable() { public void getAvailabilityStatus_withoutInit_returnsUnavailable() {
@@ -122,11 +122,11 @@ public class CredentialManagerPreferenceControllerTest {
@Test @Test
public void buildSwitchPreference() { public void buildSwitchPreference() {
CredentialProviderInfo providerInfo1 = CredentialProviderInfo providerInfo1 =
createCredentialProviderInfoWithIsEnabled( createCredentialProviderInfoWithSubtitle(
"com.android.provider1", "ClassA", "Service Title", false); "com.android.provider1", "ClassA", "Service Title", null);
CredentialProviderInfo providerInfo2 = CredentialProviderInfo providerInfo2 =
createCredentialProviderInfoWithIsEnabled( createCredentialProviderInfoWithSubtitle(
"com.android.provider2", "ClassA", "Service Title", false); "com.android.provider2", "ClassA", "Service Title", "Summary Text");
CredentialManagerPreferenceController controller = CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2)); createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
@@ -147,11 +147,13 @@ public class CredentialManagerPreferenceControllerTest {
SwitchPreference pref = controller.createPreference(mContext, providerInfo1); SwitchPreference pref = controller.createPreference(mContext, providerInfo1);
assertThat(pref.getTitle().toString()).isEqualTo("Service Title"); assertThat(pref.getTitle().toString()).isEqualTo("Service Title");
assertThat(pref.isChecked()).isTrue(); assertThat(pref.isChecked()).isTrue();
assertThat(pref.getSummary()).isNull();
// Create the pref (not checked). // Create the pref (not checked).
SwitchPreference pref2 = controller.createPreference(mContext, providerInfo2); SwitchPreference pref2 = controller.createPreference(mContext, providerInfo2);
assertThat(pref2.getTitle().toString()).isEqualTo("Service Title"); assertThat(pref2.getTitle().toString()).isEqualTo("Service Title");
assertThat(pref2.isChecked()).isFalse(); assertThat(pref2.isChecked()).isFalse();
assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text");
} }
@Test @Test
@@ -250,7 +252,7 @@ public class CredentialManagerPreferenceControllerTest {
assertThat(enabledServices.size()).isEqualTo(1); assertThat(enabledServices.size()).isEqualTo(1);
assertThat(enabledServices.contains("com.android.provider1/ClassA")).isFalse(); assertThat(enabledServices.contains("com.android.provider1/ClassA")).isFalse();
assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue(); assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue();
} }*/
@Test @Test
public void displayPreference_withServices_preferencesAdded_sameAppShouldBeMerged() { public void displayPreference_withServices_preferencesAdded_sameAppShouldBeMerged() {
@@ -297,6 +299,7 @@ public class CredentialManagerPreferenceControllerTest {
Map<String, SwitchPreference> prefs = Map<String, SwitchPreference> prefs =
controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory); controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory);
assertThat(prefs.keySet()).containsExactly(TEST_PACKAGE_NAME_A, TEST_PACKAGE_NAME_B, TEST_PACKAGE_NAME_C);
assertThat(prefs.size()).isEqualTo(3); assertThat(prefs.size()).isEqualTo(3);
assertThat(prefs.containsKey(TEST_PACKAGE_NAME_A)).isTrue(); assertThat(prefs.containsKey(TEST_PACKAGE_NAME_A)).isTrue();
assertThat(prefs.get(TEST_PACKAGE_NAME_A).getTitle()).isEqualTo(TEST_TITLE_APP_A); assertThat(prefs.get(TEST_PACKAGE_NAME_A).getTitle()).isEqualTo(TEST_TITLE_APP_A);
@@ -335,6 +338,23 @@ public class CredentialManagerPreferenceControllerTest {
.build(); .build();
} }
private CredentialProviderInfo createCredentialProviderInfoWithSubtitle(
String packageName, String className, CharSequence label, CharSequence subtitle) {
ServiceInfo si = new ServiceInfo();
si.packageName = packageName;
si.name = className;
si.nonLocalizedLabel = "test";
si.applicationInfo = new ApplicationInfo();
si.applicationInfo.packageName = packageName;
si.applicationInfo.nonLocalizedLabel = "test";
return new CredentialProviderInfo.Builder(si)
.setOverrideLabel(label)
.setSettingsSubtitle(subtitle)
.build();
}
private CredentialProviderInfo createCredentialProviderInfoWithAppLabel( private CredentialProviderInfo createCredentialProviderInfoWithAppLabel(
String packageName, String className, CharSequence serviceLabel, String appLabel) { String packageName, String className, CharSequence serviceLabel, String appLabel) {
return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, appLabel) return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, appLabel)