Code refactor for maintainance: Move subscription change monitor out of ResetnetworkConfirm Bug: 259611847 Test: local test, auto testing Change-Id: I97a251ced4435d0cc390b40028edef07fd71e24f
158 lines
5.6 KiB
Java
158 lines
5.6 KiB
Java
/*
|
|
* 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;
|
|
|
|
import android.content.Context;
|
|
import android.telephony.SubscriptionManager;
|
|
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
|
|
import android.util.Log;
|
|
|
|
import androidx.annotation.VisibleForTesting;
|
|
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.stream.IntStream;
|
|
|
|
/**
|
|
* A Class monitoring the availability of subscription IDs provided within reset request.
|
|
*
|
|
* This is to detect the situation when user changing SIM card during the presenting of
|
|
* confirmation UI.
|
|
*/
|
|
public class ResetSubscriptionContract implements AutoCloseable {
|
|
private static final String TAG = "ResetSubscriptionContract";
|
|
|
|
private final Context mContext;
|
|
private ExecutorService mExecutorService;
|
|
private final int [] mResetSubscriptionIds;
|
|
@VisibleForTesting
|
|
protected OnSubscriptionsChangedListener mSubscriptionsChangedListener;
|
|
private AtomicBoolean mSubscriptionsUpdateNotify = new AtomicBoolean();
|
|
|
|
/**
|
|
* Constructor
|
|
* @param context Context
|
|
* @param resetRequest the request object for perform network reset operation.
|
|
*/
|
|
public ResetSubscriptionContract(Context context, ResetNetworkRequest resetRequest) {
|
|
mContext = context;
|
|
// Only keeps specific subscription ID required to perform reset operation
|
|
IntStream subIdStream = IntStream.of(
|
|
resetRequest.getResetTelephonyAndNetworkPolicyManager()
|
|
, resetRequest.getResetApnSubId());
|
|
mResetSubscriptionIds = subIdStream.sorted().distinct()
|
|
.filter(id -> SubscriptionManager.isUsableSubscriptionId(id))
|
|
.toArray();
|
|
|
|
if (mResetSubscriptionIds.length <= 0) {
|
|
return;
|
|
}
|
|
|
|
// Monitoring callback through background thread
|
|
mExecutorService = Executors.newSingleThreadExecutor();
|
|
startMonitorSubscriptionChange();
|
|
}
|
|
|
|
/**
|
|
* A method for detecting if there's any subscription under monitor no longer active.
|
|
* @return subscription ID which is no longer active.
|
|
*/
|
|
public Integer getAnyMissingSubscriptionId() {
|
|
if (mResetSubscriptionIds.length <= 0) {
|
|
return null;
|
|
}
|
|
SubscriptionManager mgr = getSubscriptionManager();
|
|
if (mgr == null) {
|
|
Log.w(TAG, "Fail to access subscription manager");
|
|
return mResetSubscriptionIds[0];
|
|
}
|
|
for (int idx = 0; idx < mResetSubscriptionIds.length; idx++) {
|
|
int subId = mResetSubscriptionIds[idx];
|
|
if (mgr.getActiveSubscriptionInfo(subId) == null) {
|
|
Log.w(TAG, "SubId " + subId + " no longer active.");
|
|
return subId;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Async callback when detecting if there's any subscription under monitor no longer active.
|
|
* @param subscriptionId subscription ID which is no longer active.
|
|
*/
|
|
public void onSubscriptionInactive(int subscriptionId) {}
|
|
|
|
@VisibleForTesting
|
|
protected SubscriptionManager getSubscriptionManager() {
|
|
return mContext.getSystemService(SubscriptionManager.class);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
protected OnSubscriptionsChangedListener getChangeListener() {
|
|
return new OnSubscriptionsChangedListener() {
|
|
@Override
|
|
public void onSubscriptionsChanged() {
|
|
/**
|
|
* Reducing the processing time on main UI thread through a flag.
|
|
* Once flag get into false, which means latest callback has been
|
|
* processed.
|
|
*/
|
|
mSubscriptionsUpdateNotify.set(true);
|
|
|
|
// Back to main UI thread
|
|
mContext.getMainExecutor().execute(() -> {
|
|
// Remove notifications and perform checking.
|
|
if (mSubscriptionsUpdateNotify.getAndSet(false)) {
|
|
Integer subId = getAnyMissingSubscriptionId();
|
|
if (subId != null) {
|
|
onSubscriptionInactive(subId);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
private void startMonitorSubscriptionChange() {
|
|
SubscriptionManager mgr = getSubscriptionManager();
|
|
if (mgr == null) {
|
|
return;
|
|
}
|
|
// update monitor listener
|
|
mSubscriptionsChangedListener = getChangeListener();
|
|
|
|
mgr.addOnSubscriptionsChangedListener(
|
|
mExecutorService, mSubscriptionsChangedListener);
|
|
}
|
|
|
|
// Implementation of AutoCloseable
|
|
public void close() {
|
|
if (mExecutorService == null) {
|
|
return;
|
|
}
|
|
// Stop monitoring subscription change
|
|
SubscriptionManager mgr = getSubscriptionManager();
|
|
if (mgr != null) {
|
|
mgr.removeOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
|
|
}
|
|
// Release Executor
|
|
mExecutorService.shutdownNow();
|
|
mExecutorService = null;
|
|
}
|
|
}
|