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

Commit 53e83854 authored by Rambo Wang's avatar Rambo Wang Committed by Gerrit Code Review
Browse files

Merge "Implement main functions to consolidate signal strength request"

parents 1cfc399a 65fdd958
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -398,7 +398,7 @@ public class DeviceStateMonitor extends Handler {
     *
     * @return True if the response update should be enabled.
     */
    private boolean shouldEnableHighPowerConsumptionIndications() {
    public boolean shouldEnableHighPowerConsumptionIndications() {
        // We should enable indications reports if one of the following condition is true.
        // 1. The device is charging.
        // 2. When the screen is on.
@@ -477,6 +477,7 @@ public class DeviceStateMonitor extends Handler {
     */
    private void onUpdateDeviceState(int eventType, boolean state) {
        final boolean shouldEnableBarringInfoReportsOld = shouldEnableBarringInfoReports();
        final boolean wasHighPowerEnabled = shouldEnableHighPowerConsumptionIndications();
        switch (eventType) {
            case EVENT_SCREEN_STATE_CHANGED:
                if (mIsScreenOn == state) return;
@@ -512,6 +513,11 @@ public class DeviceStateMonitor extends Handler {
                return;
        }

        final boolean isHighPowerEnabled = shouldEnableHighPowerConsumptionIndications();
        if (wasHighPowerEnabled != isHighPowerEnabled) {
            mPhone.notifyDeviceIdleStateChanged(!isHighPowerEnabled /*isIdle*/);
        }

        final int newCellInfoMinInterval = computeCellInfoMinInterval();
        if (mCellInfoMinInterval != newCellInfoMinInterval) {
            mCellInfoMinInterval = newCellInfoMinInterval;
+6 −1
Original line number Diff line number Diff line
@@ -4054,13 +4054,18 @@ public class GsmCdmaPhone extends Phone {
    @Override
    public void setSignalStrengthReportingCriteria(
            int signalStrengthMeasure, int[] thresholds, int ran, boolean isEnabled) {
        int[] consolidatedThresholds = mSST.getConsolidatedSignalThresholds(
                ran,
                signalStrengthMeasure,
                mSST.shouldHonorSystemThresholds() ? thresholds : new int[]{},
                REPORTING_HYSTERESIS_DB);
        mCi.setSignalStrengthReportingCriteria(
                new SignalThresholdInfo.Builder()
                        .setRadioAccessNetworkType(ran)
                        .setSignalMeasurementType(signalStrengthMeasure)
                        .setHysteresisMs(REPORTING_HYSTERESIS_MILLIS)
                        .setHysteresisDb(REPORTING_HYSTERESIS_DB)
                        .setThresholds(thresholds)
                        .setThresholdsUnlimited(consolidatedThresholds)
                        .setIsEnabled(isEnabled)
                        .build(),
                ran, null);
+30 −0
Original line number Diff line number Diff line
@@ -4599,6 +4599,36 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return false;
    }

    /**
     * Check if device is idle. Device is idle when it is not in high power consumption mode.
     *
     * @see DeviceStateMonitor#shouldEnableHighPowerConsumptionIndications()
     *
     * @return true if device is idle
     */
    public boolean isDeviceIdle() {
        DeviceStateMonitor dsm = getDeviceStateMonitor();
        if (dsm == null) {
            Rlog.e(LOG_TAG, "isDeviceIdle: DeviceStateMonitor is null");
            return false;
        }
        return !dsm.shouldEnableHighPowerConsumptionIndications();
    }

    /**
     * Get notified when device idleness state has changed
     *
     * @param isIdle true if the new state is idle
     */
    public void notifyDeviceIdleStateChanged(boolean isIdle) {
        ServiceStateTracker sst = getServiceStateTracker();
        if (sst == null) {
            Rlog.e(LOG_TAG, "notifyDeviceIdleStateChanged: SST is null");
            return;
        }
        sst.onDeviceIdleStateChanged(isIdle);
    }

    /**
     * Returns a list of the equivalent home PLMNs (EF_EHPLMN) from the USIM app.
     *
+200 −0
Original line number Diff line number Diff line
@@ -44,11 +44,13 @@ import android.os.AsyncResult;
import android.os.BaseBundle;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcel;
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.TimestampedValue;
@@ -77,6 +79,7 @@ import android.telephony.PhysicalChannelConfig;
import android.telephony.ServiceState;
import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SignalStrength;
import android.telephony.SignalStrengthUpdateRequest;
import android.telephony.SignalThresholdInfo;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -125,9 +128,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -293,6 +298,9 @@ public class ServiceStateTracker extends Handler {
    protected static final int EVENT_CELL_LOCATION_RESPONSE            = 56;
    protected static final int EVENT_CARRIER_CONFIG_CHANGED            = 57;
    private static final int EVENT_POLL_STATE_REQUEST                  = 58;
    private static final int EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST = 59;
    private static final int EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST = 60;
    private static final int EVENT_ON_DEVICE_IDLE_STATE_CHANGED        = 61;

    /**
     * The current service state.
@@ -643,6 +651,9 @@ public class ServiceStateTracker extends Handler {
    private final Object mLteRsrpBoostLock = new Object();
    private static final int INVALID_LTE_EARFCN = -1;

    // @GuardedBy("mSignalRequestRecords")
    private final List<SignalRequestRecord> mSignalRequestRecords = new ArrayList<>();

    public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
        mNitzState = TelephonyComponentFactory.getInstance()
                .inject(NitzStateMachine.class.getName())
@@ -1752,6 +1763,76 @@ public class ServiceStateTracker extends Handler {
                pollStateInternal(false);
                break;

            case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST: {
                Pair<SignalRequestRecord, Message> pair =
                        (Pair<SignalRequestRecord, Message>) msg.obj;
                SignalRequestRecord record = pair.first;
                Message onCompleted = pair.second;
                AsyncResult ret = AsyncResult.forMessage(onCompleted);

                // TODO(b/177956310): Check subId to filter out old request until a better solution
                boolean dupRequest = mSignalRequestRecords.stream().anyMatch(
                        srr -> srr.mCallingUid == record.mCallingUid
                                && srr.mSubId == record.mSubId);
                if (dupRequest) {
                    ret.exception = new IllegalStateException(
                            "setSignalStrengthUpdateRequest called again with same subId");
                    onCompleted.sendToTarget();
                    break;
                }

                try {
                    record.mRequest.getLiveToken().linkToDeath(record, 0);
                } catch (RemoteException | NullPointerException ex) {
                    ret.exception = new IllegalStateException(
                            "Signal request client is already dead.");
                    onCompleted.sendToTarget();
                    break;
                }

                synchronized (mSignalRequestRecords) {
                    mSignalRequestRecords.add(record);
                }

                updateAlwaysReportSignalStrength();
                updateReportingCriteria(getCarrierConfig());

                onCompleted.sendToTarget();
                break;
            }

            case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST: {
                Pair<SignalRequestRecord, Message> pair =
                        (Pair<SignalRequestRecord, Message>) msg.obj;
                SignalRequestRecord record = pair.first;
                Message onCompleted = pair.second;

                synchronized (mSignalRequestRecords) {
                    // for loop with removal may cause ConcurrentModificationException
                    Iterator<SignalRequestRecord> it = mSignalRequestRecords.iterator();
                    while (it.hasNext()) {
                        SignalRequestRecord srr = it.next();
                        if (srr.mRequest.getLiveToken().equals(record.mRequest.getLiveToken())) {
                            it.remove();
                        }
                    }
                }

                updateAlwaysReportSignalStrength();
                updateReportingCriteria(getCarrierConfig());

                if (onCompleted != null) {
                    AsyncResult ret = AsyncResult.forMessage(onCompleted);
                    onCompleted.sendToTarget();
                }
                break;
            }

            case EVENT_ON_DEVICE_IDLE_STATE_CHANGED: {
                updateReportingCriteria(getCarrierConfig());
                break;
            }

            default:
                log("Unhandled message with number: " + msg.what);
                break;
@@ -5953,4 +6034,123 @@ public class ServiceStateTracker extends Handler {
        values.put(SERVICE_STATE, p.marshall());
        return values;
    }

    /**
     * Set a new request to update the signal strength thresholds.
     */
    public void setSignalStrengthUpdateRequest(int subId, int callingUid,
            SignalStrengthUpdateRequest request, @NonNull Message onCompleted) {
        SignalRequestRecord record = new SignalRequestRecord(subId, callingUid, request);
        sendMessage(obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST,
                new Pair<SignalRequestRecord, Message>(record, onCompleted)));
    }

    /**
     * Clear the previously set request.
     */
    public void clearSignalStrengthUpdateRequest(int subId, int callingUid,
            SignalStrengthUpdateRequest request, @Nullable Message onCompleted) {
        SignalRequestRecord record = new SignalRequestRecord(subId, callingUid, request);
        sendMessage(obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST,
                new Pair<SignalRequestRecord, Message>(record, onCompleted)));
    }

    /**
     * Align all the qualified thresholds set from applications to the {@code systemThresholds}
     * and consolidate a new thresholds array, follow rules below:
     * 1. All threshold values (whose interval is guaranteed to be larger than hysteresis) in
     *    {@code systemThresholds} will keep as it.
     * 2. Any threshold from apps that has interval less than hysteresis from any threshold in
     *    {@code systemThresholds} will be removed.
     * 3. The target thresholds will be {@code systemThresholds} + all qualified thresholds from
     *    apps, sorted in ascending order.
     */
    int[] getConsolidatedSignalThresholds(int ran, int measurement,
            int[] systemThresholds, int hysteresis) {

        // TreeSet with comparator that will filter element with interval less than hysteresis
        // from any current element
        Set<Integer> target = new TreeSet<>((x, y) -> {
            if (y >= x - hysteresis && y <= x + hysteresis) {
                return 0;
            }
            return Integer.compare(x, y);
        });

        for (int systemThreshold : systemThresholds) {
            target.add(systemThreshold);
        }

        final boolean isDeviceIdle = mPhone.isDeviceIdle();
        final int curSubId = mPhone.getSubId();
        synchronized (mSignalRequestRecords) {
            // The total number of record is small (10~15 tops). With each request has at most 5
            // SignalThresholdInfo which has at most 8 thresholds arrays. So the nested loop should
            // not be a concern here.
            for (SignalRequestRecord record : mSignalRequestRecords) {
                if (curSubId != record.mSubId
                        || (isDeviceIdle && !record.mRequest.isReportingRequestedWhileIdle())) {
                    continue;
                }
                for (SignalThresholdInfo info : record.mRequest.getSignalThresholdInfos()) {
                    if (ran == info.getRadioAccessNetworkType()
                            && measurement == info.getSignalMeasurementType()) {
                        for (int appThreshold : info.getThresholds()) {
                            target.add(appThreshold);
                        }
                    }
                }
            }
        }

        int[] targetArray = new int[target.size()];
        int i = 0;
        for (int element : target) {
            targetArray[i++] = element;
        }
        return targetArray;
    }

    boolean shouldHonorSystemThresholds() {
        if (!mPhone.isDeviceIdle()) {
            return true;
        }

        final int curSubId = mPhone.getSubId();
        return mSignalRequestRecords.stream().anyMatch(
                srr -> curSubId == srr.mSubId
                        && srr.mRequest.isSystemThresholdReportingRequestedWhileIdle());
    }

    void onDeviceIdleStateChanged(boolean isDeviceIdle) {
        sendMessage(obtainMessage(EVENT_ON_DEVICE_IDLE_STATE_CHANGED, isDeviceIdle));
    }

    private class SignalRequestRecord implements IBinder.DeathRecipient {
        final int mSubId; // subId the request originally applied to
        final int mCallingUid;
        final SignalStrengthUpdateRequest mRequest;

        SignalRequestRecord(int subId, int uid, SignalStrengthUpdateRequest request) {
            this.mCallingUid = uid;
            this.mSubId = subId;
            this.mRequest = request;
        }

        @Override
        public void binderDied() {
            clearSignalStrengthUpdateRequest(mSubId, mCallingUid, mRequest, null /*onCompleted*/);
        }
    }

    private void updateAlwaysReportSignalStrength() {
        final int curSubId = mPhone.getSubId();
        boolean alwaysReport = mSignalRequestRecords.stream().anyMatch(
                srr -> srr.mSubId == curSubId && (srr.mRequest.isReportingRequestedWhileIdle()
                        || srr.mRequest.isSystemThresholdReportingRequestedWhileIdle()));

        // TODO(b/177924721): TM#setAlwaysReportSignalStrength will be removed and we will not
        // worry about unset flag which was set by other client.
        mPhone.setAlwaysReportSignalStrength(alwaysReport);
    }
}