[Settings] Add the repository for room database

Bug: 236919685
Test: manual
Change-Id: I7f32e4eb6a976091e285ef43abcd45a9d16a6ca9
This commit is contained in:
Zoey Chen
2022-09-26 15:24:10 +00:00
parent 8e74ee57d1
commit 67ad5a31d7

View File

@@ -0,0 +1,429 @@
/*
* 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;
import static android.telephony.UiccSlotInfo.CARD_STATE_INFO_PRESENT;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccPortInfo;
import android.telephony.UiccSlotInfo;
import android.util.Log;
import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.mobile.dataservice.MobileNetworkDatabase;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoDao;
import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoDao;
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
import com.android.settingslib.mobile.dataservice.UiccInfoDao;
import com.android.settingslib.mobile.dataservice.UiccInfoEntity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptionsChangedListener {
private static final String TAG = "MobileNetworkRepository";
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private SubscriptionManager mSubscriptionManager;
private TelephonyManager mTelephonyManager;
private MobileNetworkDatabase mMobileNetworkDatabase;
private SubscriptionInfoDao mSubscriptionInfoDao;
private UiccInfoDao mUiccInfoDao;
private MobileNetworkInfoDao mMobileNetworkInfoDao;
private List<SubscriptionInfoEntity> mAvailableSubInfoEntityList = new ArrayList<>();
private List<SubscriptionInfoEntity> mActiveSubInfoEntityList = new ArrayList<>();
private List<UiccInfoEntity> mUiccInfoEntityList = new ArrayList<>();
private List<MobileNetworkInfoEntity> mMobileNetworkInfoEntityList = new ArrayList<>();
private MobileNetworkCallback mCallback;
private Context mContext;
private AirplaneModeObserver mAirplaneModeObserver;
private Uri mAirplaneModeSettingUri;
private MetricsFeatureProvider mMetricsFeatureProvider;
private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
private int mCardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
private int mPortIndex = TelephonyManager.INVALID_PORT_INDEX;
private int mCardId = TelephonyManager.UNINITIALIZED_CARD_ID;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mIsEuicc = false;
private boolean mIsRemovable = false;
private boolean mIsActive = false;
MobileNetworkRepository(Context context, MobileNetworkCallback mobileNetworkCallback) {
mContext = context;
mCallback = mobileNetworkCallback;
mMobileNetworkDatabase = MobileNetworkDatabase.createDatabase(context);
mSubscriptionInfoDao = mMobileNetworkDatabase.mSubscriptionInfoDao();
mUiccInfoDao = mMobileNetworkDatabase.mUiccInfoDao();
mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao();
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper()));
mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_MOBILE_NETWORK_DB_CREATED);
}
private class AirplaneModeObserver extends ContentObserver {
AirplaneModeObserver(Handler handler) {
super(handler);
}
public void register(Context context) {
context.getContentResolver().registerContentObserver(mAirplaneModeSettingUri, false,
this);
}
public void unRegister(Context context) {
context.getContentResolver().unregisterContentObserver(this);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (uri.equals(mAirplaneModeSettingUri)) {
mCallback.onAirplaneModeChanged(isAirplaneModeOn());
}
}
}
public void addRegister(LifecycleOwner lifecycleOwner) {
mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this);
mAirplaneModeObserver.register(mContext);
observeAllSubInfo(lifecycleOwner);
observeAllUiccInfo(lifecycleOwner);
observeAllMobileNetworkInfo(lifecycleOwner);
}
public void removeRegister() {
mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
mAirplaneModeObserver.unRegister(mContext);
mContext.getContentResolver().unregisterContentObserver(mAirplaneModeObserver);
}
private void observeAllSubInfo(LifecycleOwner lifecycleOwner) {
Log.d(TAG, "Observe subInfo.");
mMobileNetworkDatabase.queryAvailableSubInfos().observe(
lifecycleOwner, this::onAvailableSubInfoChanged);
}
private void observeAllUiccInfo(LifecycleOwner lifecycleOwner) {
Log.d(TAG, "Observe UICC info.");
mMobileNetworkDatabase.queryAllUiccInfo().observe(
lifecycleOwner, this::onAllUiccInfoChanged);
}
private void observeAllMobileNetworkInfo(LifecycleOwner lifecycleOwner) {
Log.d(TAG, "Observe mobile network info.");
mMobileNetworkDatabase.queryAllMobileNetworkInfo().observe(
lifecycleOwner, this::onAllMobileNetworkInfoChanged);
}
public List<SubscriptionInfoEntity> getAvailableSubInfoEntityList() {
return mAvailableSubInfoEntityList;
}
public List<SubscriptionInfoEntity> getActiveSubscriptionInfoList() {
return mActiveSubInfoEntityList;
}
public List<UiccInfoEntity> getUiccInfoEntityList() {
return mUiccInfoEntityList;
}
public List<MobileNetworkInfoEntity> getMobileNetworkInfoEntityList() {
return mMobileNetworkInfoEntityList;
}
public int getSubInfosCount() {
return mSubscriptionInfoDao.count();
}
public int getUiccInfosCount() {
return mUiccInfoDao.count();
}
public int getMobileNetworkInfosCount() {
return mMobileNetworkInfoDao.count();
}
private void getUiccInfoBySubscriptionInfo(UiccSlotInfo[] uiccSlotInfos,
SubscriptionInfo subInfo) {
for (int i = 0; i < uiccSlotInfos.length; i++) {
UiccSlotInfo curSlotInfo = uiccSlotInfos[i];
if (curSlotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT) {
mIsEuicc = curSlotInfo.getIsEuicc();
mCardState = curSlotInfo.getCardStateInfo();
mIsRemovable = curSlotInfo.isRemovable();
mCardId = subInfo.getCardId();
Collection<UiccPortInfo> uiccPortInfos = curSlotInfo.getPorts();
for (UiccPortInfo portInfo : uiccPortInfos) {
if (portInfo.getPortIndex() == subInfo.getPortIndex()
&& portInfo.getLogicalSlotIndex() == subInfo.getSimSlotIndex()) {
mPhysicalSlotIndex = i;
mLogicalSlotIndex = portInfo.getLogicalSlotIndex();
mIsActive = portInfo.isActive();
mPortIndex = portInfo.getPortIndex();
break;
} else {
Log.d(TAG,
"Can not get port index and physicalSlotIndex for subId " + mSubId);
}
}
if (mPhysicalSlotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
break;
}
} else {
Log.d(TAG, "Can not get card state info");
}
}
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_GET_UICC_INFO);
}
private void onAvailableSubInfoChanged(
List<SubscriptionInfoEntity> availableSubInfoEntityList) {
mAvailableSubInfoEntityList = availableSubInfoEntityList;
mActiveSubInfoEntityList = mAvailableSubInfoEntityList.stream()
.filter(SubscriptionInfoEntity::isActiveSubscription)
.filter(SubscriptionInfoEntity::isSubscriptionVisible)
.collect(Collectors.toList());
Log.d(TAG, "onAvailableSubInfoChanged, availableSubInfoEntityList = "
+ availableSubInfoEntityList);
mCallback.onAvailableSubInfoChanged(availableSubInfoEntityList);
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_SUB_INFO_IS_CHANGED);
setActiveSubInfoList(mActiveSubInfoEntityList);
}
private void setActiveSubInfoList(
List<SubscriptionInfoEntity> activeSubInfoEntityList) {
Log.d(TAG, "onActiveSubInfoChanged, activeSubInfoEntityList = " + activeSubInfoEntityList);
mCallback.onActiveSubInfoChanged(mActiveSubInfoEntityList);
}
private void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList) {
mUiccInfoEntityList = uiccInfoEntityList;
mCallback.onAllUiccInfoChanged(uiccInfoEntityList);
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_UICC_INFO_IS_CHANGED);
}
private void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
mCallback.onAllMobileNetworkInfoChanged(mobileNetworkInfoEntityList);
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_NOTIFY_MOBILE_NETWORK_INFO_IS_CHANGED);
}
public void insertSubInfo(Context context, SubscriptionInfo info) {
mExecutor.execute(() -> {
SubscriptionInfoEntity subInfoEntity =
convertToSubscriptionInfoEntity(context, info);
if (subInfoEntity != null) {
mMobileNetworkDatabase.insertSubsInfo(subInfoEntity);
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_SUB_INFO);
} else {
Log.d(TAG, "Can not insert subInfo, the entity is null");
}
});
}
public void deleteAllInfoBySubId(String subId) {
mExecutor.execute(() -> {
mMobileNetworkDatabase.deleteSubInfoBySubId(subId);
mMobileNetworkDatabase.deleteUiccInfoBySubId(subId);
mMobileNetworkDatabase.deleteMobileNetworkInfoBySubId(subId);
});
mAvailableSubInfoEntityList.removeIf(info -> info.subId.equals(subId));
mActiveSubInfoEntityList.removeIf(info -> info.subId.equals(subId));
mUiccInfoEntityList.removeIf(info -> info.subId.equals(subId));
mMobileNetworkInfoEntityList.removeIf(info -> info.subId.equals(subId));
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_DELETE_DATA);
}
public SubscriptionInfoEntity convertToSubscriptionInfoEntity(Context context,
SubscriptionInfo subInfo) {
mSubId = subInfo.getSubscriptionId();
mTelephonyManager = context.getSystemService(
TelephonyManager.class).createForSubscriptionId(mSubId);
UiccSlotInfo[] uiccSlotInfos = mTelephonyManager.getUiccSlotsInfo();
if (uiccSlotInfos == null || uiccSlotInfos.length == 0) {
Log.d(TAG, "uiccSlotInfos = null or empty");
return null;
} else {
getUiccInfoBySubscriptionInfo(uiccSlotInfos, subInfo);
insertUiccInfo();
insertMobileNetworkInfo(context);
Log.d(TAG, "convert subscriptionInfo to entity for subId = " + mSubId);
return new SubscriptionInfoEntity(String.valueOf(mSubId),
subInfo.getSimSlotIndex(),
subInfo.getCarrierId(), subInfo.getDisplayName().toString(),
subInfo.getCarrierName() != null ? subInfo.getCarrierName().toString() : "",
subInfo.getDataRoaming(), subInfo.getMccString(), subInfo.getMncString(),
subInfo.getCountryIso(), subInfo.isEmbedded(), mCardId,
subInfo.getPortIndex(), subInfo.isOpportunistic(),
String.valueOf(subInfo.getGroupUuid()),
subInfo.getSubscriptionType(),
SubscriptionUtil.getUniqueSubscriptionDisplayName(subInfo, context).toString(),
SubscriptionUtil.isSubscriptionVisible(mSubscriptionManager, context, subInfo),
SubscriptionUtil.getFormattedPhoneNumber(context, subInfo),
SubscriptionUtil.getFirstRemovableSubscription(context) == null ? false
: SubscriptionUtil.getFirstRemovableSubscription(
context).getSubscriptionId() == mSubId,
String.valueOf(SubscriptionUtil.getDefaultSimConfig(context, mSubId)),
SubscriptionUtil.getSubscriptionOrDefault(context, mSubId).getSubscriptionId()
== mSubId,
mSubscriptionManager.isValidSubscriptionId(mSubId),
mSubscriptionManager.isUsableSubscriptionId(mSubId),
mSubscriptionManager.isActiveSubscriptionId(mSubId),
true /*availableSubInfo*/,
mSubscriptionManager.getDefaultVoiceSubscriptionId() == mSubId,
mSubscriptionManager.getDefaultSmsSubscriptionId() == mSubId,
mSubscriptionManager.getDefaultDataSubscriptionId() == mSubId,
mSubscriptionManager.getDefaultSubscriptionId() == mSubId);
}
}
public void insertUiccInfo() {
mMobileNetworkDatabase.insertUiccInfo(convertToUiccInfoEntity());
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_UICC_INFO);
}
public void insertMobileNetworkInfo(Context context) {
mMobileNetworkDatabase.insertMobileNetworkInfo(convertToMobileNetworkInfoEntity(context));
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_MOBILE_NETWORK_DB_INSERT_MOBILE_NETWORK_INFO);
}
public MobileNetworkInfoEntity convertToMobileNetworkInfoEntity(Context context) {
return new MobileNetworkInfoEntity(String.valueOf(mSubId),
MobileNetworkUtils.isContactDiscoveryEnabled(context, mSubId),
MobileNetworkUtils.isContactDiscoveryVisible(context, mSubId),
MobileNetworkUtils.isMobileDataEnabled(context),
MobileNetworkUtils.isCdmaOptions(context, mSubId),
MobileNetworkUtils.isGsmOptions(context, mSubId),
MobileNetworkUtils.isWorldMode(context, mSubId),
MobileNetworkUtils.shouldDisplayNetworkSelectOptions(context, mSubId),
MobileNetworkUtils.isTdscdmaSupported(context, mSubId),
MobileNetworkUtils.activeNetworkIsCellular(context),
SubscriptionUtil.showToggleForPhysicalSim(mSubscriptionManager)
);
}
private UiccInfoEntity convertToUiccInfoEntity() {
return new UiccInfoEntity(String.valueOf(mSubId), String.valueOf(mPhysicalSlotIndex),
mLogicalSlotIndex, mCardId, mIsEuicc, isMultipleEnabledProfilesSupported(),
mCardState, mIsRemovable, mIsActive, mPortIndex
);
}
private boolean isMultipleEnabledProfilesSupported() {
List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo();
if (cardInfos == null) {
Log.w(TAG, "UICC card info list is empty.");
return false;
}
return cardInfos.stream().anyMatch(
cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
}
@Override
public void onSubscriptionsChanged() {
insertAvailableSubInfoToEntity(mSubscriptionManager.getAvailableSubscriptionInfoList());
}
private void insertAvailableSubInfoToEntity(List<SubscriptionInfo> availableInfoList) {
if ((availableInfoList == null || availableInfoList.size() == 0)
&& mAvailableSubInfoEntityList.size() != 0) {
Log.d(TAG, "availableSudInfoList from framework is empty, remove all subs");
for (SubscriptionInfoEntity info : mAvailableSubInfoEntityList) {
deleteAllInfoBySubId(info.subId);
}
} else if (availableInfoList != null) {
for (SubscriptionInfo subInfo : availableInfoList) {
if (availableInfoList.size() < mAvailableSubInfoEntityList.size()) {
Optional<SubscriptionInfoEntity> infoEntity =
mAvailableSubInfoEntityList.stream().filter(
info -> subInfo.getSubscriptionId()
!= Integer.parseInt(info.subId)).findFirst();
if (infoEntity.isPresent()) {
Log.d(TAG, "delete sudInfo " + infoEntity.get().subId
+ " from subInfoEntity");
deleteAllInfoBySubId(infoEntity.get().subId);
}
}
Log.d(TAG, "insert sudInfo " + subInfo.getSubscriptionId() + " to subInfoEntity");
insertSubInfo(mContext, subInfo);
}
}
}
public boolean isAirplaneModeOn() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
/**
* Callback for clients to get the latest info changes if the framework or content observers.
* updates the relevant info.
*/
interface MobileNetworkCallback {
void onAvailableSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList);
void onActiveSubInfoChanged(List<SubscriptionInfoEntity> subInfoEntityList);
void onAllUiccInfoChanged(List<UiccInfoEntity> uiccInfoEntityList);
void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList);
void onAirplaneModeChanged(boolean enabled);
}
}