Merge "Refactor the EntitlementManager" am: 581afa0bfa

Change-Id: I20f7b03356592cd184b695e4ceb491d4b04cde14
This commit is contained in:
Mark Chien
2020-05-07 11:19:16 +00:00
committed by Automerger Merge Worker

View File

@@ -45,13 +45,13 @@ import android.os.SystemClock;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.provider.Settings; import android.provider.Settings;
import android.telephony.CarrierConfigManager; import android.telephony.CarrierConfigManager;
import android.util.ArraySet;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine; import com.android.internal.util.StateMachine;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.BitSet;
/** /**
* Re-check tethering provisioning for enabled downstream tether types. * Re-check tethering provisioning for enabled downstream tether types.
@@ -74,11 +74,11 @@ public class EntitlementManager {
private final ComponentName mSilentProvisioningService; private final ComponentName mSilentProvisioningService;
private static final int MS_PER_HOUR = 60 * 60 * 1000; private static final int MS_PER_HOUR = 60 * 60 * 1000;
// The ArraySet contains enabled downstream types, ex: // The BitSet is the bit map of each enabled downstream types, ex:
// {@link TetheringManager.TETHERING_WIFI} // {@link TetheringManager.TETHERING_WIFI}
// {@link TetheringManager.TETHERING_USB} // {@link TetheringManager.TETHERING_USB}
// {@link TetheringManager.TETHERING_BLUETOOTH} // {@link TetheringManager.TETHERING_BLUETOOTH}
private final ArraySet<Integer> mCurrentTethers; private final BitSet mCurrentDownstreams;
private final Context mContext; private final Context mContext;
private final int mPermissionChangeMessageCode; private final int mPermissionChangeMessageCode;
private final SharedLog mLog; private final SharedLog mLog;
@@ -87,9 +87,9 @@ public class EntitlementManager {
private final StateMachine mTetherMasterSM; private final StateMachine mTetherMasterSM;
// Key: TetheringManager.TETHERING_*(downstream). // Key: TetheringManager.TETHERING_*(downstream).
// Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result). // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
private final SparseIntArray mCellularPermitted; private final SparseIntArray mCurrentEntitlementResults;
private PendingIntent mProvisioningRecheckAlarm; private PendingIntent mProvisioningRecheckAlarm;
private boolean mCellularUpstreamPermitted = true; private boolean mLastCellularUpstreamPermitted = true;
private boolean mUsingCellularAsUpstream = false; private boolean mUsingCellularAsUpstream = false;
private boolean mNeedReRunProvisioningUi = false; private boolean mNeedReRunProvisioningUi = false;
private OnUiEntitlementFailedListener mListener; private OnUiEntitlementFailedListener mListener;
@@ -97,11 +97,10 @@ public class EntitlementManager {
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log, public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode) { int permissionChangeMessageCode) {
mContext = ctx; mContext = ctx;
mLog = log.forSubComponent(TAG); mLog = log.forSubComponent(TAG);
mCurrentTethers = new ArraySet<Integer>(); mCurrentDownstreams = new BitSet();
mCellularPermitted = new SparseIntArray(); mCurrentEntitlementResults = new SparseIntArray();
mEntitlementCacheValue = new SparseIntArray(); mEntitlementCacheValue = new SparseIntArray();
mTetherMasterSM = tetherMasterSM; mTetherMasterSM = tetherMasterSM;
mPermissionChangeMessageCode = permissionChangeMessageCode; mPermissionChangeMessageCode = permissionChangeMessageCode;
@@ -144,13 +143,19 @@ public class EntitlementManager {
* Check if cellular upstream is permitted. * Check if cellular upstream is permitted.
*/ */
public boolean isCellularUpstreamPermitted() { public boolean isCellularUpstreamPermitted() {
// If provisioning is required and EntitlementManager don't know any downstream,
// cellular upstream should not be allowed.
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (mCurrentTethers.size() == 0 && isTetherProvisioningRequired(config)) {
return false; return isCellularUpstreamPermitted(config);
} }
return mCellularUpstreamPermitted;
private boolean isCellularUpstreamPermitted(final TetheringConfiguration config) {
if (!isTetherProvisioningRequired(config)) return true;
// If provisioning is required and EntitlementManager doesn't know any downstreams,
// cellular upstream should not be allowed.
if (mCurrentDownstreams.isEmpty()) return false;
return mCurrentEntitlementResults.indexOfValue(TETHER_ERROR_NO_ERROR) > -1;
} }
/** /**
@@ -164,15 +169,11 @@ public class EntitlementManager {
public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) { public void startProvisioningIfNeeded(int downstreamType, boolean showProvisioningUi) {
if (!isValidDownstreamType(downstreamType)) return; if (!isValidDownstreamType(downstreamType)) return;
if (!mCurrentTethers.contains(downstreamType)) mCurrentTethers.add(downstreamType); mCurrentDownstreams.set(downstreamType, true);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (isTetherProvisioningRequired(config)) { if (!isTetherProvisioningRequired(config)) return;
// If provisioning is required and the result is not available yet,
// cellular upstream should not be allowed.
if (mCellularPermitted.size() == 0) {
mCellularUpstreamPermitted = false;
}
// If upstream is not cellular, provisioning app would not be launched // If upstream is not cellular, provisioning app would not be launched
// till upstream change to cellular. // till upstream change to cellular.
if (mUsingCellularAsUpstream) { if (mUsingCellularAsUpstream) {
@@ -185,9 +186,6 @@ public class EntitlementManager {
} else { } else {
mNeedReRunProvisioningUi |= showProvisioningUi; mNeedReRunProvisioningUi |= showProvisioningUi;
} }
} else {
mCellularUpstreamPermitted = true;
}
} }
/** /**
@@ -195,14 +193,14 @@ public class EntitlementManager {
* *
* @param type tethering type from TetheringManager.TETHERING_{@code *} * @param type tethering type from TetheringManager.TETHERING_{@code *}
*/ */
public void stopProvisioningIfNeeded(int type) { public void stopProvisioningIfNeeded(int downstreamType) {
if (!isValidDownstreamType(type)) return; if (!isValidDownstreamType(downstreamType)) return;
mCurrentTethers.remove(type); mCurrentDownstreams.set(downstreamType, false);
// There are lurking bugs where the notion of "provisioning required" or // There are lurking bugs where the notion of "provisioning required" or
// "tethering supported" may change without without tethering being notified properly. // "tethering supported" may change without without tethering being notified properly.
// Remove the mapping all the time no matter provisioning is required or not. // Remove the mapping all the time no matter provisioning is required or not.
removeDownstreamMapping(type); removeDownstreamMapping(downstreamType);
} }
/** /**
@@ -213,7 +211,7 @@ public class EntitlementManager {
public void notifyUpstream(boolean isCellular) { public void notifyUpstream(boolean isCellular) {
if (DBG) { if (DBG) {
mLog.i("notifyUpstream: " + isCellular mLog.i("notifyUpstream: " + isCellular
+ ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted
+ ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi); + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi);
} }
mUsingCellularAsUpstream = isCellular; mUsingCellularAsUpstream = isCellular;
@@ -231,7 +229,7 @@ public class EntitlementManager {
} }
private void maybeRunProvisioning(final TetheringConfiguration config) { private void maybeRunProvisioning(final TetheringConfiguration config) {
if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) { if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) {
return; return;
} }
@@ -239,8 +237,9 @@ public class EntitlementManager {
// are allowed. Therefore even if the silent check here ends in a failure and the UI later // are allowed. Therefore even if the silent check here ends in a failure and the UI later
// yields success, then the downstream that got a failure will re-evaluate as a result of // yields success, then the downstream that got a failure will re-evaluate as a result of
// the change and get the new correct value. // the change and get the new correct value.
for (Integer downstream : mCurrentTethers) { for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0;
if (mCellularPermitted.indexOfKey(downstream) < 0) { downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) {
if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) {
if (mNeedReRunProvisioningUi) { if (mNeedReRunProvisioningUi) {
mNeedReRunProvisioningUi = false; mNeedReRunProvisioningUi = false;
runUiTetherProvisioning(downstream, config.activeDataSubId); runUiTetherProvisioning(downstream, config.activeDataSubId);
@@ -286,7 +285,7 @@ public class EntitlementManager {
mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread"); mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread");
} }
mEntitlementCacheValue.clear(); mEntitlementCacheValue.clear();
mCellularPermitted.clear(); mCurrentEntitlementResults.clear();
// TODO: refine provisioning check to isTetherProvisioningRequired() ?? // TODO: refine provisioning check to isTetherProvisioningRequired() ??
if (!config.hasMobileHotspotProvisionApp() if (!config.hasMobileHotspotProvisionApp()
@@ -410,22 +409,21 @@ public class EntitlementManager {
} }
private void evaluateCellularPermission(final TetheringConfiguration config) { private void evaluateCellularPermission(final TetheringConfiguration config) {
final boolean oldPermitted = mCellularUpstreamPermitted; final boolean oldPermitted = mLastCellularUpstreamPermitted;
mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config) mLastCellularUpstreamPermitted = isCellularUpstreamPermitted(config);
|| mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1);
if (DBG) { if (DBG) {
mLog.i("Cellular permission change from " + oldPermitted mLog.i("Cellular permission change from " + oldPermitted
+ " to " + mCellularUpstreamPermitted); + " to " + mLastCellularUpstreamPermitted);
} }
if (mCellularUpstreamPermitted != oldPermitted) { if (mLastCellularUpstreamPermitted != oldPermitted) {
mLog.log("Cellular permission change: " + mCellularUpstreamPermitted); mLog.log("Cellular permission change: " + mLastCellularUpstreamPermitted);
mTetherMasterSM.sendMessage(mPermissionChangeMessageCode); mTetherMasterSM.sendMessage(mPermissionChangeMessageCode);
} }
// Only schedule periodic re-check when tether is provisioned // Only schedule periodic re-check when tether is provisioned
// and the result is ok. // and the result is ok.
if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) { if (mLastCellularUpstreamPermitted && mCurrentEntitlementResults.size() > 0) {
scheduleProvisioningRechecks(config); scheduleProvisioningRechecks(config);
} else { } else {
cancelTetherProvisioningRechecks(); cancelTetherProvisioningRechecks();
@@ -441,10 +439,10 @@ public class EntitlementManager {
*/ */
protected void addDownstreamMapping(int type, int resultCode) { protected void addDownstreamMapping(int type, int resultCode) {
mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode
+ " ,TetherTypeRequested: " + mCurrentTethers.contains(type)); + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type));
if (!mCurrentTethers.contains(type)) return; if (!mCurrentDownstreams.get(type)) return;
mCellularPermitted.put(type, resultCode); mCurrentEntitlementResults.put(type, resultCode);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config); evaluateCellularPermission(config);
} }
@@ -455,7 +453,7 @@ public class EntitlementManager {
*/ */
protected void removeDownstreamMapping(int type) { protected void removeDownstreamMapping(int type) {
mLog.i("removeDownstreamMapping: " + type); mLog.i("removeDownstreamMapping: " + type);
mCellularPermitted.delete(type); mCurrentEntitlementResults.delete(type);
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration(); final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
evaluateCellularPermission(config); evaluateCellularPermission(config);
} }
@@ -488,14 +486,15 @@ public class EntitlementManager {
* @param pw {@link PrintWriter} is used to print formatted * @param pw {@link PrintWriter} is used to print formatted
*/ */
public void dump(PrintWriter pw) { public void dump(PrintWriter pw) {
pw.print("mCellularUpstreamPermitted: "); pw.print("isCellularUpstreamPermitted: ");
pw.println(mCellularUpstreamPermitted); pw.println(isCellularUpstreamPermitted());
for (Integer type : mCurrentTethers) { for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0;
type = mCurrentDownstreams.nextSetBit(type + 1)) {
pw.print("Type: "); pw.print("Type: ");
pw.print(typeString(type)); pw.print(typeString(type));
if (mCellularPermitted.indexOfKey(type) > -1) { if (mCurrentEntitlementResults.indexOfKey(type) > -1) {
pw.print(", Value: "); pw.print(", Value: ");
pw.println(errorString(mCellularPermitted.get(type))); pw.println(errorString(mCurrentEntitlementResults.get(type)));
} else { } else {
pw.println(", Value: empty"); pw.println(", Value: empty");
} }