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

Commit 30c08f0b authored by Daniel Bright's avatar Daniel Bright Committed by Android (Google) Code Review
Browse files

Merge "Add apn throttle status notifications to QNS"

parents 74d95a7e c47c3984
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -11086,6 +11086,35 @@ package android.telephony.data {
    field public static final String TYPE_XCAP_STRING = "xcap";
  }
  public final class ApnThrottleStatus implements android.os.Parcelable {
    method public int describeContents();
    method public int getApnType();
    method public int getRetryType();
    method public int getSlotIndex();
    method public long getThrottleExpiryTimeMillis();
    method public int getThrottleType();
    method public int getTransportType();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.ApnThrottleStatus> CREATOR;
    field public static final int RETRY_TYPE_HANDOVER = 3; // 0x3
    field public static final int RETRY_TYPE_NEW_CONNECTION = 2; // 0x2
    field public static final int RETRY_TYPE_NONE = 1; // 0x1
    field public static final int THROTTLE_TYPE_ELAPSED_TIME = 2; // 0x2
    field public static final int THROTTLE_TYPE_NONE = 1; // 0x1
  }
  public static final class ApnThrottleStatus.Builder {
    ctor public ApnThrottleStatus.Builder();
    method @NonNull public android.telephony.data.ApnThrottleStatus build();
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setApnType(int);
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setNoThrottle();
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setRetryType(int);
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setSlotIndex(int);
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setThrottleExpiryTimeMillis(long);
    method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setTransportType(int);
    field public static final long NO_THROTTLE_EXPIRY_TIME = -1L; // 0xffffffffffffffffL
  }
  public final class DataCallResponse implements android.os.Parcelable {
    method public int describeContents();
    method @NonNull public java.util.List<android.net.LinkAddress> getAddresses();
@@ -11203,6 +11232,7 @@ package android.telephony.data {
    method public abstract void close();
    method public void deactivateDataCall(int, int, @Nullable android.telephony.data.DataServiceCallback);
    method public final int getSlotIndex();
    method public final void notifyApnUnthrottled(@NonNull String);
    method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
    method public void requestDataCallList(@NonNull android.telephony.data.DataServiceCallback);
    method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
@@ -11213,6 +11243,7 @@ package android.telephony.data {
  }
  public class DataServiceCallback {
    method public void onApnUnthrottled(@NonNull String);
    method public void onDataCallListChanged(@NonNull java.util.List<android.telephony.data.DataCallResponse>);
    method public void onDeactivateDataCallComplete(int);
    method public void onHandoverCancelled(int);
@@ -11238,6 +11269,7 @@ package android.telephony.data {
    ctor public QualifiedNetworksService.NetworkAvailabilityProvider(int);
    method public abstract void close();
    method public final int getSlotIndex();
    method public void reportApnThrottleStatusChanged(@NonNull java.util.List<android.telephony.data.ApnThrottleStatus>);
    method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
  }
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */

/** @hide */
package android.telephony.data;

parcelable ApnThrottleStatus;
+383 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 android.telephony.data;

import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation;

import java.util.Objects;

/**
 * Status information regarding the throttle status of an APN type.
 *
 * @hide
 */
@SystemApi
public final class ApnThrottleStatus implements Parcelable {
    /**
     * The APN type is not throttled.
     */
    public static final int THROTTLE_TYPE_NONE = 1;

    /**
     * The APN type is throttled until {@link android.os.SystemClock#elapsedRealtime()}
     * has reached {@link ApnThrottleStatus#getThrottleExpiryTimeMillis}
     */
    public static final int THROTTLE_TYPE_ELAPSED_TIME = 2;

    /** {@hide} */
    @IntDef(flag = true, prefix = {"THROTTLE_TYPE_"}, value = {
            ApnThrottleStatus.THROTTLE_TYPE_NONE,
            ApnThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME,
    })
    public @interface ThrottleType {
    }

    /**
     * The framework will not retry the APN type.
     */
    public static final int RETRY_TYPE_NONE = 1;

    /**
     * The next time the framework retries, it will attempt to establish a new connection.
     */
    public static final int RETRY_TYPE_NEW_CONNECTION = 2;

    /**
     * The next time the framework retires, it will retry to handover.
     */
    public static final int RETRY_TYPE_HANDOVER = 3;

    /** {@hide} */
    @IntDef(flag = true, prefix = {"RETRY_TYPE_"}, value = {
            ApnThrottleStatus.RETRY_TYPE_NONE,
            ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION,
            ApnThrottleStatus.RETRY_TYPE_HANDOVER,
    })
    public @interface RetryType {
    }

    private final int mSlotIndex;
    private final @AccessNetworkConstants.TransportType int mTransportType;
    private final @Annotation.ApnType int mApnType;
    private final long mThrottleExpiryTimeMillis;
    private final @RetryType int mRetryType;
    private final @ThrottleType int mThrottleType;

    /**
     * The slot index that the status applies to.
     *
     * @return the slot index
     */
    public int getSlotIndex() {
        return mSlotIndex;
    }

    /**
     * The type of transport that the status applies to.
     *
     * @return the transport type
     */
    @AccessNetworkConstants.TransportType
    public int getTransportType() {
        return mTransportType;
    }

    /**
     * The APN type that the status applies to.
     *
     * @return the apn type
     */
    @Annotation.ApnType
    public int getApnType() {
        return mApnType;
    }

    /**
     * The type of throttle applied to the APN type.
     *
     * @return the throttle type
     */
    @ThrottleType
    public int getThrottleType() {
        return mThrottleType;
    }

    /**
     * Indicates the type of request that the framework will make the next time it retries
     * to call {@link IDataService#setupDataCall}.
     *
     * @return the retry type
     */
    @RetryType
    public int getRetryType() {
        return mRetryType;
    }

    /**
     * Gets the time at which the throttle expires.  The value is based off of
     * {@link SystemClock#elapsedRealtime}.
     *
     * This value only applies when the throttle type is set to
     * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
     *
     * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely.
     *
     * @return the time at which the throttle expires
     */
    @ElapsedRealtimeLong
    public long getThrottleExpiryTimeMillis() {
        return mThrottleExpiryTimeMillis;
    }

    private ApnThrottleStatus(int slotIndex,
            @AccessNetworkConstants.TransportType int transportType,
            @Annotation.ApnType int apnTypes,
            @ThrottleType int throttleType,
            long throttleExpiryTimeMillis,
            @RetryType int retryType) {
        mSlotIndex = slotIndex;
        mTransportType = transportType;
        mApnType = apnTypes;
        mThrottleType = throttleType;
        mThrottleExpiryTimeMillis = throttleExpiryTimeMillis;
        mRetryType = retryType;
    }

    private ApnThrottleStatus(@NonNull Parcel source) {
        mSlotIndex = source.readInt();
        mTransportType = source.readInt();
        mApnType = source.readInt();
        mThrottleExpiryTimeMillis = source.readLong();
        mRetryType = source.readInt();
        mThrottleType = source.readInt();
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeInt(mSlotIndex);
        dest.writeInt(mTransportType);
        dest.writeInt(mApnType);
        dest.writeLong(mThrottleExpiryTimeMillis);
        dest.writeInt(mRetryType);
        dest.writeInt(mThrottleType);
    }

    public static final @NonNull Parcelable.Creator<ApnThrottleStatus> CREATOR =
            new Parcelable.Creator<ApnThrottleStatus>() {
                @Override
                public ApnThrottleStatus createFromParcel(@NonNull Parcel source) {
                    return new ApnThrottleStatus(source);
                }

                @Override
                public ApnThrottleStatus[] newArray(int size) {
                    return new ApnThrottleStatus[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public int hashCode() {
        return Objects.hash(mSlotIndex, mApnType, mRetryType, mThrottleType,
                mThrottleExpiryTimeMillis, mTransportType);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        } else if (obj instanceof ApnThrottleStatus) {
            ApnThrottleStatus other = (ApnThrottleStatus) obj;
            return this.mSlotIndex == other.mSlotIndex
                    && this.mApnType == other.mApnType
                    && this.mRetryType == other.mRetryType
                    && this.mThrottleType == other.mThrottleType
                    && this.mThrottleExpiryTimeMillis == other.mThrottleExpiryTimeMillis
                    && this.mTransportType == other.mTransportType;
        } else {
            return false;
        }
    }

    @Override
    public String toString() {
        return "ApnThrottleStatus{"
                + "mSlotIndex=" + mSlotIndex
                + ", mTransportType=" + mTransportType
                + ", mApnType=" + ApnSetting.getApnTypeString(mApnType)
                + ", mThrottleExpiryTimeMillis=" + mThrottleExpiryTimeMillis
                + ", mRetryType=" + mRetryType
                + ", mThrottleType=" + mThrottleType
                + '}';
    }

    /**
     * Provides a convenient way to set the fields of an {@link ApnThrottleStatus} when creating a
     * new instance.
     *
     * <p>The example below shows how you might create a new {@code ApnThrottleStatus}:
     *
     * <pre><code>
     *
     * DataCallResponseApnThrottleStatus = new ApnThrottleStatus.Builder()
     *     .setSlotIndex(1)
     *     .setApnType({@link ApnSetting#TYPE_EMERGENCY})
     *     .setNoThrottle()
     *     .setRetryType({@link ApnThrottleStatus#RETRY_TYPE_NEW_CONNECTION})
     *     .build();
     * </code></pre>
     */
    public static final class Builder {
        private int mSlotIndex;
        private @AccessNetworkConstants.TransportType int mTransportType;
        private @Annotation.ApnType int mApnType;
        private long mThrottleExpiryTimeMillis;
        private @RetryType int mRetryType;
        private @ThrottleType int mThrottleType;
        public static final long NO_THROTTLE_EXPIRY_TIME =
                DataCallResponse.RETRY_DURATION_UNDEFINED;

        /**
         * Default constructor for the Builder.
         */
        public Builder() {
        }

        /**
         * Set the slot index.
         *
         * @param slotIndex the slot index.
         * @return The same instance of the builder.
         */
        @NonNull
        public Builder setSlotIndex(int slotIndex) {
            this.mSlotIndex = slotIndex;
            return this;
        }

        /**
         * Set the transport type.
         *
         * @param transportType the transport type.
         * @return The same instance of the builder.
         */
        @NonNull
        public Builder setTransportType(@AccessNetworkConstants.TransportType
                int transportType) {
            this.mTransportType = transportType;
            return this;
        }

        /**
         * Set the APN type.
         *
         * @param apnType  the APN type.
         * @return The same instance of the builder.
         */
        @NonNull
        public Builder setApnType(@Annotation.ApnType int apnType) {
            this.mApnType = apnType;
            return this;
        }

        /**
         * Sets the time at which the throttle will expire.  The value is based off of
         * {@link SystemClock#elapsedRealtime}.
         *
         * When setting this value, the throttle type is set to
         * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
         *
         * A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely.
         *
         * @param throttleExpiryTimeMillis The elapsed time at which the throttle expires.
         *                                 Throws {@link IllegalArgumentException} for values less
         *                                 than 0.
         * @return The same instance of the builder.
         */
        @NonNull
        public Builder setThrottleExpiryTimeMillis(
                @ElapsedRealtimeLong long throttleExpiryTimeMillis) {
            if (throttleExpiryTimeMillis >= 0) {
                this.mThrottleExpiryTimeMillis = throttleExpiryTimeMillis;
                this.mThrottleType = THROTTLE_TYPE_ELAPSED_TIME;
            } else {
                throw new IllegalArgumentException("throttleExpiryTimeMillis must be greater than "
                        + "or equal to 0");
            }
            return this;
        }

        /**
         * Sets the status of the APN type as not being throttled.
         *
         * When setting this value, the throttle type is set to
         * {@link ApnThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to
         * {@link Builder#NO_THROTTLE_EXPIRY_TIME}.
         *
         * @return The same instance of the builder.
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        @NonNull
        public Builder setNoThrottle() {
            mThrottleType = THROTTLE_TYPE_NONE;
            mThrottleExpiryTimeMillis = NO_THROTTLE_EXPIRY_TIME;
            return this;
        }

        /**
         * Set the type of request that the framework will make the next time it retries
         * to call {@link IDataService#setupDataCall}.
         *
         * @param retryType the type of request
         * @return The same instance of the builder.
         */
        @NonNull
        public Builder setRetryType(@RetryType int retryType) {
            this.mRetryType = retryType;
            return this;
        }

        /**
         * Build the {@link ApnThrottleStatus}
         *
         * @return the {@link ApnThrottleStatus} object
         */
        @NonNull
        public ApnThrottleStatus build() {
            return new ApnThrottleStatus(
                    mSlotIndex,
                    mTransportType,
                    mApnType,
                    mThrottleType,
                    mThrottleExpiryTimeMillis,
                    mRetryType);
        }
    }
}
+83 −0
Original line number Diff line number Diff line
@@ -107,6 +107,9 @@ public abstract class DataService extends Service {
    private static final int DATA_SERVICE_INDICATION_DATA_CALL_LIST_CHANGED            = 11;
    private static final int DATA_SERVICE_REQUEST_START_HANDOVER                       = 12;
    private static final int DATA_SERVICE_REQUEST_CANCEL_HANDOVER                      = 13;
    private static final int DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED             = 14;
    private static final int DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED           = 15;
    private static final int DATA_SERVICE_INDICATION_APN_UNTHROTTLED                   = 16;

    private final HandlerThread mHandlerThread;

@@ -129,6 +132,8 @@ public abstract class DataService extends Service {

        private final List<IDataServiceCallback> mDataCallListChangedCallbacks = new ArrayList<>();

        private final List<IDataServiceCallback> mApnUnthrottledCallbacks = new ArrayList<>();

        /**
         * Constructor
         * @param slotIndex SIM slot index the data service provider associated with.
@@ -326,6 +331,19 @@ public abstract class DataService extends Service {
            }
        }

        private void registerForApnUnthrottled(IDataServiceCallback callback) {
            synchronized (mApnUnthrottledCallbacks) {
                mApnUnthrottledCallbacks.add(callback);
            }
        }

        private void unregisterForApnUnthrottled(IDataServiceCallback callback) {
            synchronized (mApnUnthrottledCallbacks) {
                mApnUnthrottledCallbacks.remove(callback);
            }
        }


        /**
         * Notify the system that current data call list changed. Data service must invoke this
         * method whenever there is any data call status changed.
@@ -342,6 +360,21 @@ public abstract class DataService extends Service {
            }
        }

        /**
         * Notify the system that a given APN was unthrottled.
         *
         * @param apn Access Point Name defined by the carrier.
         */
        public final void notifyApnUnthrottled(@NonNull String apn) {
            synchronized (mApnUnthrottledCallbacks) {
                for (IDataServiceCallback callback : mApnUnthrottledCallbacks) {
                    mHandler.obtainMessage(DATA_SERVICE_INDICATION_APN_UNTHROTTLED,
                            mSlotIndex, 0, new ApnUnthrottledIndication(apn,
                                    callback)).sendToTarget();
                }
            }
        }

        /**
         * Called when the instance of data service is destroyed (e.g. got unbind or binder died)
         * or when the data service provider is removed. The extended class should implement this
@@ -429,6 +462,16 @@ public abstract class DataService extends Service {
        }
    }

    private static final class ApnUnthrottledIndication {
        public final String apn;
        public final IDataServiceCallback callback;
        ApnUnthrottledIndication(String apn,
                IDataServiceCallback callback) {
            this.apn = apn;
            this.callback = callback;
        }
    }

    private class DataServiceHandler extends Handler {

        DataServiceHandler(Looper looper) {
@@ -544,6 +587,26 @@ public abstract class DataService extends Service {
                            (cReq.callback != null)
                                    ? new DataServiceCallback(cReq.callback) : null);
                    break;
                case DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED:
                    if (serviceProvider == null) break;
                    serviceProvider.registerForApnUnthrottled((IDataServiceCallback) message.obj);
                    break;
                case DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED:
                    if (serviceProvider == null) break;
                    callback = (IDataServiceCallback) message.obj;
                    serviceProvider.unregisterForApnUnthrottled(callback);
                    break;
                case DATA_SERVICE_INDICATION_APN_UNTHROTTLED:
                    if (serviceProvider == null) break;
                    ApnUnthrottledIndication apnUnthrottledIndication =
                            (ApnUnthrottledIndication) message.obj;
                    try {
                        apnUnthrottledIndication.callback
                                .onApnUnthrottled(apnUnthrottledIndication.apn);
                    } catch (RemoteException e) {
                        loge("Failed to call onApnUnthrottled. " + e);
                    }
                    break;
            }
        }
    }
@@ -695,6 +758,26 @@ public abstract class DataService extends Service {
            mHandler.obtainMessage(DATA_SERVICE_REQUEST_CANCEL_HANDOVER,
                    slotIndex, 0, req).sendToTarget();
        }

        @Override
        public void registerForUnthrottleApn(int slotIndex, IDataServiceCallback callback) {
            if (callback == null) {
                loge("registerForUnthrottleApn: callback is null");
                return;
            }
            mHandler.obtainMessage(DATA_SERVICE_REQUEST_REGISTER_APN_UNTHROTTLED, slotIndex,
                    0, callback).sendToTarget();
        }

        @Override
        public void unregisterForUnthrottleApn(int slotIndex, IDataServiceCallback callback) {
            if (callback == null) {
                loge("uregisterForUnthrottleApn: callback is null");
                return;
            }
            mHandler.obtainMessage(DATA_SERVICE_REQUEST_UNREGISTER_APN_UNTHROTTLED,
                    slotIndex, 0, callback).sendToTarget();
        }
    }

    private void log(String s) {
+19 −1
Original line number Diff line number Diff line
@@ -248,4 +248,22 @@ public class DataServiceCallback {
                return "Missing case for result code=" + resultCode;
        }
    }

    /**
     * Indicates that the specified APN is no longer throttled.
     *
     * @param apn Access Point Name defined by the carrier.
     */
    public void onApnUnthrottled(@NonNull String apn) {
        if (mCallback != null) {
            try {
                if (DBG) Rlog.d(TAG, "onApnUnthrottled");
                mCallback.onApnUnthrottled(apn);
            } catch (RemoteException e) {
                Rlog.e(TAG, "onApnUnthrottled: remote exception", e);
            }
        } else {
            Rlog.e(TAG, "onApnUnthrottled: callback is null!");
        }
    }
}
Loading