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

Commit 43835f40 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes I02995faf,If51829ab,I6cb09aa0

* changes:
  Added prototype for internet validation registration
  Added network request evaluation result
  Fixed crash in dump
parents 631bddd4 d2bf4cc8
Loading
Loading
Loading
Loading
+221 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.internal.telephony.data;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;

import java.text.DateFormat;
import java.util.HashSet;
import java.util.Set;

/**
 * The class to describe the result of environment evaluation for whether allowing or disallowing
 * establishing a data network.
 */
public class DataEvaluationResult {
    /** Data disallowed reasons. There could be multiple reasons for not allowing data. */
    private @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();

    /** Data allowed reason. It is intended to only have one allowed reason. */
    private DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;

    /** The timestamp of evaluation time */
    private @CurrentTimeMillisLong long mEvaluatedTime = 0;

    /**
     * Add a data disallowed reason. Note that adding a disallowed reason will clean up the
     * allowed reason because they are mutual exclusive.
     *
     * @param reason Disallowed reason.
     */
    public void add(DataDisallowedReason reason) {
        mDataAllowedReason = DataAllowedReason.NONE;
        mDataDisallowedReasons.add(reason);
        mEvaluatedTime = System.currentTimeMillis();
    }

    /**
     * Add a data allowed reason. Note that adding an allowed reason will clean up the disallowed
     * reasons because they are mutual exclusive.
     *
     * @param reason Allowed reason.
     */
    public void add(DataAllowedReason reason) {
        mDataDisallowedReasons.clear();

        // Only higher priority allowed reason can overwrite the old one. See
        // DataAllowedReason for the oder.
        if (reason.ordinal() > mDataAllowedReason.ordinal()) {
            mDataAllowedReason = reason;
        }
        mEvaluatedTime = System.currentTimeMillis();
    }

    @Override
    public String toString() {
        StringBuilder reasonStr = new StringBuilder();
        reasonStr.append("EvaluationResult: ");
        if (mDataDisallowedReasons.size() > 0) {
            reasonStr.append("Data disallowed reasons:");
            for (DataDisallowedReason reason : mDataDisallowedReasons) {
                reasonStr.append(" ").append(reason);
            }
        } else {
            reasonStr.append("Data allowed reason:");
            reasonStr.append(" ").append(mDataAllowedReason);
        }
        reasonStr.append(", time=" + DateFormat.getDateTimeInstance().format(mEvaluatedTime));
        return reasonStr.toString();
    }

    /**
     * @return {@code true} if data is allowed.
     */
    public boolean isDataAllowed() {
        return mDataDisallowedReasons.size() == 0;
    }

    /**
     * Check if it contains a certain disallowed reason.
     *
     * @param reason The disallowed reason to check.
     * @return {@code true} if the provided reason matches one of the disallowed reasons.
     */
    public boolean contains(DataDisallowedReason reason) {
        return mDataDisallowedReasons.contains(reason);
    }

    /**
     * Check if only one disallowed reason prevent data connection.
     *
     * @param reason The given reason to check
     * @return True if the given reason is the only one that prevents data connection
     */
    public boolean containsOnly(DataDisallowedReason reason) {
        return mDataDisallowedReasons.size() == 1 && contains(reason);
    }

    /**
     * Check if the allowed reason is the specified reason.
     *
     * @param reason The allowed reason.
     * @return {@code true} if the specified reason matches the allowed reason.
     */
    public boolean contains(DataAllowedReason reason) {
        return reason == mDataAllowedReason;
    }

    /**
     * @return {@code true} if the disallowed reasons contains hard reasons.
     */
    public boolean containsHardDisallowedReasons() {
        for (DataDisallowedReason reason : mDataDisallowedReasons) {
            if (reason.isHardReason()) {
                return true;
            }
        }
        return false;
    }

    /** Disallowed reasons. There could be multiple reasons if data connection is not allowed. */
    public enum DataDisallowedReason {
        // Soft failure reasons. A soft reason means that in certain conditions, data is still
        // allowed. Normally those reasons are due to users settings.

        /** Data is disabled by the user or policy. */
        DATA_DISABLED(false),
        /** Data roaming is disabled by the user. */
        ROAMING_DISABLED(false),
        /** Default data not selected. */
        DEFAULT_DATA_UNSELECTED(false),

        // Belows are all hard failure reasons. A hard reason means no matter what the data should
        // not be allowed.
        /** Data registration state is not in service. */
        NOT_IN_SERVICE(true),
        /** SIM is not ready. */
        SIM_NOT_READY(true),
        /** Concurrent voice and data is not allowed. */
        CONCURRENT_VOICE_DATA_NOT_ALLOWED(true),
        /** Carrier notified data should be restricted. */
        DATA_RESTRICTED_BY_NETWORK(true),
        /** Radio power is off (i.e. airplane mode on) */
        RADIO_POWER_OFF(true),
        /** Data disabled by telephony in some scenarios, for example, emergency call. */
        INTERNAL_DATA_DISABLED(true),
        /** Airplane mode is forcibly turned on by the carrier. */
        RADIO_DISABLED_BY_CARRIER(true),
        /** certain APNs are only allowed when the device is camped on NR. */
        NOT_ON_NR(true),
        /** Data is not allowed while device is in emergency callback mode. */
        IN_ECBM(true),
        /** Underlying data service is not bound. */
        DATA_SERVICE_NOT_READY(true);

        private final boolean mIsHardReason;

        /**
         * @return {@code true} if the disallowed reason is a hard reason.
         */
        public boolean isHardReason() {
            return mIsHardReason;
        }

        /**
         * Constructor
         *
         * @param isHardReason {@code true} if the disallowed reason is a hard reason. A hard reason
         * means no matter what the data should not be allowed. A soft reason means that in certain
         * conditions, data is still allowed.
         */
        DataDisallowedReason(boolean isHardReason) {
            mIsHardReason = isHardReason;
        }
    }

    /**
     * Data allowed reasons. There will be only one reason if data is allowed.
     */
    enum DataAllowedReason {
        // Note that unlike disallowed reasons, we only have one allowed reason every time
        // when we check data is allowed or not. The order of these allowed reasons is very
        // important. The lower ones take precedence over the upper ones.
        /**
         * None. This is the initial value.
         */
        NONE,
        /**
         * The normal reason. This is the most common case.
         */
        NORMAL,
        /**
         * The network brought up by this network request is unmetered. Should allowed no matter
         * the user enables or disables data.
         */
        UNMETERED_USAGE,
        /**
         * The network request is restricted (i.e. Only privilege apps can access the network.)
         */
        RESTRICTED_REQUEST,
        /**
         * Data is allowed because the network request is for emergency. This should be always at
         * the bottom (i.e. highest priority)
         */
        EMERGENCY_REQUEST,
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.net.NetworkRequest;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RegistrantList;
import android.os.SystemProperties;
import android.telephony.AccessNetworkConstants;
import android.telephony.data.DataProfile;
@@ -145,6 +146,8 @@ public class DataNetworkController extends Handler {
    private final @NonNull NetworkRequestList mActivelyProcessedNetworkRequestList =
            new NetworkRequestList();

    private final RegistrantList mInternetValidationStatusRegistrants = new RegistrantList();

    /**
     * The sorted network request list by priority. The highest priority network request stays at
     * the head of the list. The highest priority is 100, the lowest is 0.
@@ -215,7 +218,8 @@ public class DataNetworkController extends Handler {
        mDataConfigManager = new DataConfigManager(mPhone, looper);
        mDataSettingsManager = new DataSettingsManager(mPhone, looper);
        mDataProfileManager = new DataProfileManager(mPhone, looper);
        mDataStallMonitor = new DataStallMonitor(mPhone, looper);
        mDataStallMonitor = new DataStallMonitor(mPhone, this, mDataServiceManagers
                .get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), looper);
        mDataTaskManager = new DataTaskManager(mPhone, looper);

        registerAllEvents();
@@ -406,6 +410,16 @@ public class DataNetworkController extends Handler {
        return mPhone.getHalVersion().less(RIL.RADIO_HAL_VERSION_1_4);
    }

    /**
     * Register for internet data network validation status changed event.
     *
     * @param handler The handler to handle the event.
     * @param what The event.
     */
    public void registerForInternetValidationStatusChanged(@NonNull Handler handler, int what) {
        mInternetValidationStatusRegistrants.addUnique(handler, what, null);
    }

    /**
     * Log debug messages.
     * @param s debug messages
+55 −4
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony.data;

import android.annotation.NonNull;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -34,25 +35,75 @@ import java.io.PrintWriter;
 * actions to recover
 */
public class DataStallMonitor extends Handler {
    private final Phone mPhone;
    private final String mLogTag;
    private final LocalLog mLocalLog = new LocalLog(128);
    /** Event for data config updated. */
    private static final int EVENT_DATA_CONFIG_UPDATED = 1;

    /** Event for internet validation status changed. */
    private static final int EVENT_INTERNET_VALIDATION_STATUS_CHANGED = 2;


    private final @NonNull Phone mPhone;
    private final @NonNull String mLogTag;
    private final @NonNull LocalLog mLocalLog = new LocalLog(128);

    /** Data network controller */
    private final @NonNull DataNetworkController mDataNetworkController;

    /** Data config manager */
    private final @NonNull DataConfigManager mDataConfigManager;

    /** Cellular data service */
    private final @NonNull DataServiceManager mWwanDataServiceManager;

    /**
     * Constructor
     *
     * @param phone The phone instance.
     * @param dataServiceManager The WWAN data service manager.
     * @param looper The looper to be used by the handler. Currently the handler thread is the
     * phone process's main thread.
     */
    public DataStallMonitor(Phone phone, Looper looper) {
    public DataStallMonitor(@NonNull Phone phone,
            @NonNull DataNetworkController dataNetworkController,
            @NonNull DataServiceManager dataServiceManager, @NonNull Looper looper) {
        super(looper);
        mPhone = phone;
        mLogTag = "DSTMTR-" + mPhone.getPhoneId();
        mDataNetworkController = dataNetworkController;
        mWwanDataServiceManager = dataServiceManager;
        mDataConfigManager = mDataNetworkController.getDataConfigManager();

        mDataConfigManager.registerForConfigUpdate(this, EVENT_DATA_CONFIG_UPDATED);
        mDataNetworkController.registerForInternetValidationStatusChanged(this,
                EVENT_INTERNET_VALIDATION_STATUS_CHANGED);
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EVENT_DATA_CONFIG_UPDATED:
                onDataConfigUpdated();
                break;
            case EVENT_INTERNET_VALIDATION_STATUS_CHANGED:
                AsyncResult ar = (AsyncResult) msg.obj;
                Boolean isValid = (Boolean) ar.result;
                onInternetValidationStatusChanged(isValid);
                break;
        }
    }

    /**
     * Called when data config was updated.
     */
    private void onDataConfigUpdated() {
    }

    /**
     * Called when internet validation status changed.
     *
     * @param isValid {@code true} if internet validation succeeded.
     */
    private void onInternetValidationStatusChanged(boolean isValid) {

    }

+3 −2
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ public class DataUtils {
     * @param netCap Network capability.
     * @return Network capability in string format.
     */
    public static String networkCapabilityToString(int netCap) {
    public static @NonNull String networkCapabilityToString(int netCap) {
        switch (netCap) {
            case NetworkCapabilities.NET_CAPABILITY_MMS:                  return "MMS";
            case NetworkCapabilities.NET_CAPABILITY_SUPL:                 return "SUPL";
@@ -111,7 +111,8 @@ public class DataUtils {
     * @param netCaps Network capabilities.
     * @return Network capabilities in string format.
     */
    public static String networkCapabilitiesToString(int[] netCaps) {
    public static @NonNull String networkCapabilitiesToString(int[] netCaps) {
        if (netCaps == null) return "";
        return Arrays.stream(netCaps)
                .mapToObj(DataUtils::networkCapabilityToString)
                .collect(Collectors.joining("|"));