Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ee8de4e authored by Mark Chien's avatar Mark Chien Committed by Automerger Merge Worker
Browse files

Merge "Refactor the EntitlementManager" am: 741e2db5 am: 6dc0be2b

Change-Id: Ib409b85729972e23242551beb39638aaefad0584
parents bd62d13b 6dc0be2b
Loading
Loading
Loading
Loading
+56 −57
Original line number Diff line number Diff line
@@ -45,13 +45,13 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.util.ArraySet;
import android.util.SparseIntArray;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.StateMachine;

import java.io.PrintWriter;
import java.util.BitSet;

/**
 * Re-check tethering provisioning for enabled downstream tether types.
@@ -74,11 +74,11 @@ public class EntitlementManager {
    private final ComponentName mSilentProvisioningService;
    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_USB}
    // {@link TetheringManager.TETHERING_BLUETOOTH}
    private final ArraySet<Integer> mCurrentTethers;
    private final BitSet mCurrentDownstreams;
    private final Context mContext;
    private final int mPermissionChangeMessageCode;
    private final SharedLog mLog;
@@ -87,9 +87,9 @@ public class EntitlementManager {
    private final StateMachine mTetherMasterSM;
    // Key: TetheringManager.TETHERING_*(downstream).
    // Value: TetheringManager.TETHER_ERROR_{NO_ERROR or PROVISION_FAILED}(provisioning result).
    private final SparseIntArray mCellularPermitted;
    private final SparseIntArray mCurrentEntitlementResults;
    private PendingIntent mProvisioningRecheckAlarm;
    private boolean mCellularUpstreamPermitted = true;
    private boolean mLastCellularUpstreamPermitted = true;
    private boolean mUsingCellularAsUpstream = false;
    private boolean mNeedReRunProvisioningUi = false;
    private OnUiEntitlementFailedListener mListener;
@@ -97,11 +97,10 @@ public class EntitlementManager {

    public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
            int permissionChangeMessageCode) {

        mContext = ctx;
        mLog = log.forSubComponent(TAG);
        mCurrentTethers = new ArraySet<Integer>();
        mCellularPermitted = new SparseIntArray();
        mCurrentDownstreams = new BitSet();
        mCurrentEntitlementResults = new SparseIntArray();
        mEntitlementCacheValue = new SparseIntArray();
        mTetherMasterSM = tetherMasterSM;
        mPermissionChangeMessageCode = permissionChangeMessageCode;
@@ -144,13 +143,19 @@ public class EntitlementManager {
     * Check if cellular upstream is permitted.
     */
    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();
        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) {
        if (!isValidDownstreamType(downstreamType)) return;

        if (!mCurrentTethers.contains(downstreamType)) mCurrentTethers.add(downstreamType);
        mCurrentDownstreams.set(downstreamType, true);

        final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
        if (isTetherProvisioningRequired(config)) {
            // If provisioning is required and the result is not available yet,
            // cellular upstream should not be allowed.
            if (mCellularPermitted.size() == 0) {
                mCellularUpstreamPermitted = false;
            }
        if (!isTetherProvisioningRequired(config)) return;

        // If upstream is not cellular, provisioning app would not be launched
        // till upstream change to cellular.
        if (mUsingCellularAsUpstream) {
@@ -185,9 +186,6 @@ public class EntitlementManager {
        } else {
            mNeedReRunProvisioningUi |= showProvisioningUi;
        }
        } else {
            mCellularUpstreamPermitted = true;
        }
    }

    /**
@@ -195,14 +193,14 @@ public class EntitlementManager {
     *
     * @param type tethering type from TetheringManager.TETHERING_{@code *}
     */
    public void stopProvisioningIfNeeded(int type) {
        if (!isValidDownstreamType(type)) return;
    public void stopProvisioningIfNeeded(int downstreamType) {
        if (!isValidDownstreamType(downstreamType)) return;

        mCurrentTethers.remove(type);
        mCurrentDownstreams.set(downstreamType, false);
        // There are lurking bugs where the notion of "provisioning required" or
        // "tethering supported" may change without without tethering being notified properly.
        // 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) {
        if (DBG) {
            mLog.i("notifyUpstream: " + isCellular
                    + ", mCellularUpstreamPermitted: " + mCellularUpstreamPermitted
                    + ", mLastCellularUpstreamPermitted: " + mLastCellularUpstreamPermitted
                    + ", mNeedReRunProvisioningUi: " + mNeedReRunProvisioningUi);
        }
        mUsingCellularAsUpstream = isCellular;
@@ -231,7 +229,7 @@ public class EntitlementManager {
    }

    private void maybeRunProvisioning(final TetheringConfiguration config) {
        if (mCurrentTethers.size() == 0 || !isTetherProvisioningRequired(config)) {
        if (mCurrentDownstreams.isEmpty() || !isTetherProvisioningRequired(config)) {
            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
        // yields success, then the downstream that got a failure will re-evaluate as a result of
        // the change and get the new correct value.
        for (Integer downstream : mCurrentTethers) {
            if (mCellularPermitted.indexOfKey(downstream) < 0) {
        for (int downstream = mCurrentDownstreams.nextSetBit(0); downstream >= 0;
                downstream = mCurrentDownstreams.nextSetBit(downstream + 1)) {
            if (mCurrentEntitlementResults.indexOfKey(downstream) < 0) {
                if (mNeedReRunProvisioningUi) {
                    mNeedReRunProvisioningUi = false;
                    runUiTetherProvisioning(downstream, config.activeDataSubId);
@@ -286,7 +285,7 @@ public class EntitlementManager {
            mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread");
        }
        mEntitlementCacheValue.clear();
        mCellularPermitted.clear();
        mCurrentEntitlementResults.clear();

        // TODO: refine provisioning check to isTetherProvisioningRequired() ??
        if (!config.hasMobileHotspotProvisionApp()
@@ -410,22 +409,21 @@ public class EntitlementManager {
    }

    private void evaluateCellularPermission(final TetheringConfiguration config) {
        final boolean oldPermitted = mCellularUpstreamPermitted;
        mCellularUpstreamPermitted = (!isTetherProvisioningRequired(config)
                || mCellularPermitted.indexOfValue(TETHER_ERROR_NO_ERROR) > -1);
        final boolean oldPermitted = mLastCellularUpstreamPermitted;
        mLastCellularUpstreamPermitted = isCellularUpstreamPermitted(config);

        if (DBG) {
            mLog.i("Cellular permission change from " + oldPermitted
                    + " to " + mCellularUpstreamPermitted);
                    + " to " + mLastCellularUpstreamPermitted);
        }

        if (mCellularUpstreamPermitted != oldPermitted) {
            mLog.log("Cellular permission change: " + mCellularUpstreamPermitted);
        if (mLastCellularUpstreamPermitted != oldPermitted) {
            mLog.log("Cellular permission change: " + mLastCellularUpstreamPermitted);
            mTetherMasterSM.sendMessage(mPermissionChangeMessageCode);
        }
        // Only schedule periodic re-check when tether is provisioned
        // and the result is ok.
        if (mCellularUpstreamPermitted && mCellularPermitted.size() > 0) {
        if (mLastCellularUpstreamPermitted && mCurrentEntitlementResults.size() > 0) {
            scheduleProvisioningRechecks(config);
        } else {
            cancelTetherProvisioningRechecks();
@@ -441,10 +439,10 @@ public class EntitlementManager {
     */
    protected void addDownstreamMapping(int type, int resultCode) {
        mLog.i("addDownstreamMapping: " + type + ", result: " + resultCode
                + " ,TetherTypeRequested: " + mCurrentTethers.contains(type));
        if (!mCurrentTethers.contains(type)) return;
                + " ,TetherTypeRequested: " + mCurrentDownstreams.get(type));
        if (!mCurrentDownstreams.get(type)) return;

        mCellularPermitted.put(type, resultCode);
        mCurrentEntitlementResults.put(type, resultCode);
        final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
        evaluateCellularPermission(config);
    }
@@ -455,7 +453,7 @@ public class EntitlementManager {
     */
    protected void removeDownstreamMapping(int type) {
        mLog.i("removeDownstreamMapping: " + type);
        mCellularPermitted.delete(type);
        mCurrentEntitlementResults.delete(type);
        final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
        evaluateCellularPermission(config);
    }
@@ -488,14 +486,15 @@ public class EntitlementManager {
     * @param pw {@link PrintWriter} is used to print formatted
     */
    public void dump(PrintWriter pw) {
        pw.print("mCellularUpstreamPermitted: ");
        pw.println(mCellularUpstreamPermitted);
        for (Integer type : mCurrentTethers) {
        pw.print("isCellularUpstreamPermitted: ");
        pw.println(isCellularUpstreamPermitted());
        for (int type = mCurrentDownstreams.nextSetBit(0); type >= 0;
                type = mCurrentDownstreams.nextSetBit(type + 1)) {
            pw.print("Type: ");
            pw.print(typeString(type));
            if (mCellularPermitted.indexOfKey(type) > -1) {
            if (mCurrentEntitlementResults.indexOfKey(type) > -1) {
                pw.print(", Value: ");
                pw.println(errorString(mCellularPermitted.get(type)));
                pw.println(errorString(mCurrentEntitlementResults.get(type)));
            } else {
                pw.println(", Value: empty");
            }