Add ThermalMitigation API to Telephony.

go/telephony-thermal-mitigation

Test: make, cts
Bug: 158872959

Change-Id: Ib4be5edf063e4c54e9238b0403f59e1621df671e
Merged-In: Ib4be5edf063e4c54e9238b0403f59e1621df671e
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index bb72096..e312a70 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9615,6 +9615,25 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataSpecificRegistrationInfo> CREATOR;
   }
 
+  public final class DataThrottlingRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getCompletionDurationMillis();
+    method public int getDataThrottlingAction();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.DataThrottlingRequest> CREATOR;
+    field public static final int DATA_THROTTLING_ACTION_HOLD = 3; // 0x3
+    field public static final int DATA_THROTTLING_ACTION_NO_DATA_THROTTLING = 0; // 0x0
+    field public static final int DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER = 2; // 0x2
+    field public static final int DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER = 1; // 0x1
+  }
+
+  public static final class DataThrottlingRequest.Builder {
+    ctor public DataThrottlingRequest.Builder();
+    method @NonNull public android.telephony.DataThrottlingRequest build();
+    method @NonNull public android.telephony.DataThrottlingRequest.Builder setCompletionDurationMillis(long);
+    method @NonNull public android.telephony.DataThrottlingRequest.Builder setDataThrottlingAction(int);
+  }
+
   public final class ImsiEncryptionInfo implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public String getKeyIdentifier();
@@ -10196,6 +10215,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void resetOtaEmergencyNumberDbFilePath();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
@@ -10313,6 +10333,11 @@
     field public static final int SRVCC_STATE_HANDOVER_FAILED = 2; // 0x2
     field public static final int SRVCC_STATE_HANDOVER_NONE = -1; // 0xffffffff
     field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
+    field public static final int THERMAL_MITIGATION_RESULT_INVALID_STATE = 3; // 0x3
+    field public static final int THERMAL_MITIGATION_RESULT_MODEM_ERROR = 1; // 0x1
+    field public static final int THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE = 2; // 0x2
+    field public static final int THERMAL_MITIGATION_RESULT_SUCCESS = 0; // 0x0
+    field public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4; // 0x4
   }
 
   public static interface TelephonyManager.CallForwardingInfoCallback {
@@ -10324,6 +10349,24 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
+  public final class ThermalMitigationRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.telephony.DataThrottlingRequest getDataThrottlingRequest();
+    method public int getThermalMitigationAction();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ThermalMitigationRequest> CREATOR;
+    field public static final int THERMAL_MITIGATION_ACTION_DATA_THROTTLING = 0; // 0x0
+    field public static final int THERMAL_MITIGATION_ACTION_RADIO_OFF = 2; // 0x2
+    field public static final int THERMAL_MITIGATION_ACTION_VOICE_ONLY = 1; // 0x1
+  }
+
+  public static final class ThermalMitigationRequest.Builder {
+    ctor public ThermalMitigationRequest.Builder();
+    method @NonNull public android.telephony.ThermalMitigationRequest build();
+    method @NonNull public android.telephony.ThermalMitigationRequest.Builder setDataThrottlingRequest(@NonNull android.telephony.DataThrottlingRequest);
+    method @NonNull public android.telephony.ThermalMitigationRequest.Builder setThermalMitigationAction(int);
+  }
+
   public final class UiccAccessRule implements android.os.Parcelable {
     ctor public UiccAccessRule(byte[], @Nullable String, long);
     method public int describeContents();
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 031c337..f900c38 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -634,4 +634,15 @@
             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA,
             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE})
     public @interface OverrideNetworkType {}
+
+    /**
+     *  Result of a thermal mitigation request.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "THERMAL_MITIGATION_RESULT_" }, value = {
+        TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS,
+        TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR,
+        TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE,
+        TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR})
+    public @interface ThermalMitigationResult {}
 }
diff --git a/telephony/java/android/telephony/DataThrottlingRequest.aidl b/telephony/java/android/telephony/DataThrottlingRequest.aidl
new file mode 100644
index 0000000..e1a3b66
--- /dev/null
+++ b/telephony/java/android/telephony/DataThrottlingRequest.aidl
@@ -0,0 +1,19 @@
+/*
+* 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;
+
+parcelable DataThrottlingRequest;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/DataThrottlingRequest.java b/telephony/java/android/telephony/DataThrottlingRequest.java
new file mode 100644
index 0000000..f50bb58
--- /dev/null
+++ b/telephony/java/android/telephony/DataThrottlingRequest.java
@@ -0,0 +1,244 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Class stores information related to the type of data throttling request. Must be populated as
+ * field in {@link ThermalMitigationRequest} for sending of thermal mitigation request at {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)}.
+ * @hide
+ */
+@SystemApi
+public final class DataThrottlingRequest implements Parcelable {
+    /**
+     * Clear all existing data throttling, enable data, and attempt to enable radio for thermal
+     * mitigation all within the requested completion window. Note that attempting to enable radio
+     * will not guarantee that radio will actually be enabled.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int DATA_THROTTLING_ACTION_NO_DATA_THROTTLING = 0;
+
+    /**
+     * Enact secondary carrier data throttling within specified completion window. This also
+     * attempts to enables radio if currently disabled for thermal mitigation, enables data, and
+     * removes any existing data throttling on primary carrier. Note that attempting to enable radio
+     * will not guarantee that radio will actually be enabled.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER = 1;
+
+    /**
+     * Enact primary carrier data throttling within specified completion window. This also attempts
+     * to enable radio if currently disabled for thermal mitigation and disables data on secondary
+     * carrier if currently enabled. Note that attempting to enable radio will not guarantee that
+     * radio will actually be enabled.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER = 2;
+
+    /**
+     * Immediately hold on to the current level of data throttling indicating that the current level
+     * of data throttling has alleviated the thermal concerns which caused the original data
+     * throttling request. A thermal module should remain actively monitoring the temperature levels
+     * and request an appropriate thermal mitigation action. {@link
+     * #THERMAL_MITIGATION_RESULT_INVALID_PARAMETERS} will be returned if completion window is not
+     * 0.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int DATA_THROTTLING_ACTION_HOLD = 3;
+
+    /**
+     * Type of data throttling action to carry out.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "DATA_THROTTLING_ACTION_" }, value = {
+        DATA_THROTTLING_ACTION_NO_DATA_THROTTLING,
+        DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER,
+        DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER,
+        DATA_THROTTLING_ACTION_HOLD})
+    public @interface DataThrottlingAction {}
+
+    /**
+     * Represents the data throttling action that will be requested. See {@link
+     * DATA_THROTTLING_ACTION_NO_DATA_THROTTLING}, {@link
+     * #DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER}, {@link
+     * #DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER}, and {@link
+     * #DATA_THROTTLING_ACTION_HOLD} for more details.
+     **/
+    private @DataThrottlingAction int mDataThrottlingAction;
+    /**
+     * Represents the time over which modem should gradually execute the data thorttling request.
+     */
+    private long mCompletionDurationMillis;
+
+    private DataThrottlingRequest(@NonNull int dataThrottlingAction,
+            long completionDurationMillis) {
+        mDataThrottlingAction = dataThrottlingAction;
+        mCompletionDurationMillis = completionDurationMillis;
+    }
+
+    private DataThrottlingRequest(Parcel in) {
+        mDataThrottlingAction = in.readInt();
+        mCompletionDurationMillis = in.readLong();
+    }
+
+    /**
+     * Implement the Parcelable interface
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mDataThrottlingAction);
+        dest.writeLong(mCompletionDurationMillis);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "[DataThrottlingRequest "
+            + ", DataThrottlingAction=" + mDataThrottlingAction
+            + ", completionDurationMillis=" + mCompletionDurationMillis
+            + "]";
+    }
+
+    /**
+    * @return the dataThrottlingAction.
+    */
+    public @DataThrottlingAction int getDataThrottlingAction() {
+        return mDataThrottlingAction;
+    }
+
+    /**
+     * @return the completionDurationMillis which represents the time over which modem should
+     * gradually execute the data thorttling request.
+     */
+    public long getCompletionDurationMillis() {
+        return mCompletionDurationMillis;
+    }
+
+    public static final @NonNull Parcelable.Creator<DataThrottlingRequest> CREATOR =
+            new Parcelable.Creator<DataThrottlingRequest>() {
+
+        @Override
+        public DataThrottlingRequest createFromParcel(Parcel in) {
+            return new DataThrottlingRequest(in);
+        }
+
+        @Override
+        public DataThrottlingRequest[] newArray(int size) {
+            return new DataThrottlingRequest[size];
+        }
+    };
+
+    /**
+     * Provides a convenient way to set the fields of a {@link DataThrottlingRequest} when creating
+     * a new instance.
+     *
+     * <p>The example below shows how you might create a new {@code DataThrottlingRequest}:
+     *
+     * <pre><code>
+     *
+     * DataThrottlingRequest dp = new DataThrottlingRequest.Builder()
+     *     .setDataThrottlingAction(
+     *          DataThrottlingRequest.DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER)
+     *     .setCompletionDurationMillis(10000L)
+     *     .build();
+     * </code></pre>
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class Builder {
+        private @DataThrottlingAction int mDataThrottlingAction;
+        private long mCompletionDurationMillis;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {}
+
+        /**
+         * Set the data throttling action.
+         *
+         * @param dataThrottlingAction data throttling action.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setDataThrottlingAction(
+                @DataThrottlingAction int dataThrottlingAction) {
+            mDataThrottlingAction = dataThrottlingAction;
+            return this;
+        }
+
+        /**
+         * Set the completion duration.
+         *
+         * @param completionDurationMillis completion duration in millis which represents the time
+         *      over which modem should gradually execute the data thorttling request. This can
+         *      never be a negative number and must be 0 for {@link #DATA_THROTTLING_ACTION_HOLD}.
+         *      Otherwise, an IllegalArgumentException will be thrown.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setCompletionDurationMillis(long completionDurationMillis) {
+            mCompletionDurationMillis = completionDurationMillis;
+            return this;
+        }
+
+        /**
+         * Build the DataThrottlingRequest.
+         *
+         * @return the DataThrottlingRequest object.
+         */
+        public @NonNull DataThrottlingRequest build() {
+            if (mCompletionDurationMillis < 0) {
+                throw new IllegalArgumentException("completionDurationMillis cannot be a negative "
+                        + "number");
+            }
+
+            if (mDataThrottlingAction == DataThrottlingRequest.DATA_THROTTLING_ACTION_HOLD
+                    && mCompletionDurationMillis != 0) {
+                throw new IllegalArgumentException("completionDurationMillis must be 0 for "
+                    + "DataThrottlingRequest.DATA_THROTTLING_ACTION_HOLD");
+            }
+
+            return new DataThrottlingRequest(mDataThrottlingAction, mCompletionDurationMillis);
+        }
+    }
+
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d156907..d36dd77 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -76,6 +76,7 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
+import android.telephony.Annotation.ThermalMitigationResult;
 import android.telephony.Annotation.UiccAppType;
 import android.telephony.CallForwardingInfo.CallForwardingReason;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
@@ -14043,4 +14044,106 @@
 
         return Collections.emptyList();
     }
+
+    /**
+     * Indicates that the thermal mitigation request was completed successfully.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_RESULT_SUCCESS = 0;
+
+    /**
+     * Indicates that the thermal mitigation request was not completed because of a modem error.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_RESULT_MODEM_ERROR = 1;
+
+    /**
+     * Indicates that the thermal mitigation request was not completed because the modem is not
+     * available.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE = 2;
+
+    /**
+     * Indicates that the thermal mitigation request could not power off the radio due to the device
+     * either being in an active voice call, device pending an emergency call, or any other state
+     * that would dissallow powering off of radio.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_RESULT_INVALID_STATE = 3;
+
+    /**
+     * Indicates that the thermal mitigation request resulted an unknown error.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR = 4;
+
+    /**
+     * Thermal mitigation request to control functionalities at modem. Thermal mitigation is done
+     * per-subscription. Caller must be sure to bind the TelephonyManager instance to subId by
+     * calling {@link #createForSubscriptionId(int)} if they want thermal mitigation on a specific
+     * subscription Id. Otherwise, TelephonyManager will use the default subscription.
+     *
+     * Calling this does not guarantee that the thermal mitigation action requested was done to
+     * completion. A thermal module should actively monitor the temperature levels and request an
+     * appropriate thermal mitigation action. Every action is assumed to be done 'on top of' the
+     * previous action, where the order of actions from least thermal mitigation to most is as
+     * follows:
+     * <ol>
+     *   <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_DATA_THROTTLING}</li>
+     *   <ol>
+     *      <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_NO_DATA_THROTTLING}</li>
+     *      <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER}</li>
+     *      <li>{@link DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER}</li>
+     *   </ol>
+     *   <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY}</li>
+     *   <li>{@link ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF}</li>
+     * </ol>
+     *
+     * So, for example, requesting {@link
+     * DataThrottlingRequest#DATA_THROTTLING_ACTION_THROTTLE_PRIMARY_CARRIER} will ensure that the
+     * data on secondary carrier has been disabled before throttling on primary carrier. {@link
+     * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_VOICE_ONLY} will ensure that data on both
+     * primary and secondary have been disabled. {@link
+     * ThermalMitigationRequest#THERMAL_MITIGATION_ACTION_RADIO_OFF} will ensure that voice is
+     * disabled and that data on both primary and secondary carriers are disabled before turning
+     * radio off. {@link DataThrottlingRequest#DATA_THROTTLING_ACTION_HOLD} is not part of the order
+     * and can be used at any time during data throttling to hold onto the current level of data
+     * throttling.
+     *
+     * @param thermalMitigationRequest Thermal mitigation request. See {@link
+     * ThermalMitigationRequest} for details.
+     *
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     * @throws IllegalArgumentException if the thermalMitigationRequest had invalid parameters.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @ThermalMitigationResult
+    public int sendThermalMitigationRequest(
+            @NonNull ThermalMitigationRequest thermalMitigationRequest) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.sendThermalMitigationRequest(getSubId(), thermalMitigationRequest);
+            }
+            throw new IllegalStateException("telephony service is null.");
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Telephony#thermalMitigationRequest RemoteException", ex);
+            ex.rethrowFromSystemServer();
+        }
+        return THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
+    }
 }
diff --git a/telephony/java/android/telephony/ThermalMitigationRequest.aidl b/telephony/java/android/telephony/ThermalMitigationRequest.aidl
new file mode 100644
index 0000000..a912f77
--- /dev/null
+++ b/telephony/java/android/telephony/ThermalMitigationRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+package android.telephony;
+
+parcelable ThermalMitigationRequest;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/ThermalMitigationRequest.java b/telephony/java/android/telephony/ThermalMitigationRequest.java
new file mode 100644
index 0000000..91ad9c3
--- /dev/null
+++ b/telephony/java/android/telephony/ThermalMitigationRequest.java
@@ -0,0 +1,248 @@
+/*
+ * 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;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Class stores information related to the type of data throttling request to be sent to {@link
+ * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)}.
+ * @hide
+ */
+@SystemApi
+public final class ThermalMitigationRequest implements Parcelable {
+    /**
+     * Sent as a thermal mititgation action to {@link
+     * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to start data
+     * throttling. {@link TelephonyManager#InvalidThermalMitigationRequestException} will be thrown
+     * if dataThrottlingRequest is {@code null} or if completion duration is < 0.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_ACTION_DATA_THROTTLING = 0;
+
+    /**
+     * Sent as a thermal mititgation action to {@link
+     * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to allow only voice
+     * calls and internet data will not be available. This attempts to enable radio if currently
+     * disabled for thermal mitigation with no guarantee of it actually turning on.
+     * dataThrottlingRequest must be {@code null} or {@link
+     * TelephonyManager#InvalidThermalMitigationRequestException} will be thrown.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_ACTION_VOICE_ONLY = 1;
+
+    /**
+     * Sent as a thermal mititgation action to {@link'
+     * TelephonyManager#sendThermalMitigationRequest(ThermalMitigationResult)} to turn radio off. If
+     * radio is not able to be powered off because of an ongoing voice call, pending emergency call,
+     * or any other state that wouldn't allow radio off, {@link
+     * TelephonyManager#THERMAL_MITIGATION_RESULT_INVALID_STATE}.
+     * dataThrottlingRequest must be {@code null} or
+     * {@link TelephonyManager#InvalidThermalMitigationRequestException} will be returned.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int THERMAL_MITIGATION_ACTION_RADIO_OFF = 2;
+
+    /**
+     * Type of thermal mitigation action.
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "THERMAL_MITIGATION_ACTION_" }, value = {
+        THERMAL_MITIGATION_ACTION_DATA_THROTTLING,
+        THERMAL_MITIGATION_ACTION_VOICE_ONLY,
+        THERMAL_MITIGATION_ACTION_RADIO_OFF})
+    public @interface ThermalMitigationAction {}
+
+    private @ThermalMitigationAction int mThermalMitigationAction;
+    private DataThrottlingRequest mDataThrottlingRequest;
+
+    /**
+     * @param thermalMitigationAction thermal mitigation action.
+     * @param dataThrottlingRequest is the parameters for more fine-controlled data throttling. This
+     * is only applicable if thermalMitigationAction is
+     * {@link #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}. Otherwise, it must be set to
+     * {@code null}. See {@link DataThrottlingRequest} for more details.
+     */
+    private ThermalMitigationRequest(@ThermalMitigationAction int thermalMitigationAction,
+            @Nullable DataThrottlingRequest dataThrottlingRequest) {
+        mThermalMitigationAction = thermalMitigationAction;
+        mDataThrottlingRequest = dataThrottlingRequest;
+    }
+
+    private ThermalMitigationRequest(Parcel in) {
+        mThermalMitigationAction = in.readInt();
+        mDataThrottlingRequest = in.readParcelable(DataThrottlingRequest.class.getClassLoader());
+    }
+
+     /**
+     * Implement the Parcelable interface
+     */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mThermalMitigationAction);
+        dest.writeParcelable(mDataThrottlingRequest, 0);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public String toString() {
+        return "[ThermalMitigationRequest "
+            + ", thermalMitigationAction=" + mThermalMitigationAction
+            + ", dataThrottlingRequest=" + mDataThrottlingRequest
+            + "]";
+    }
+
+    /**
+     * @return the thermal mitigation action.
+     */
+    public @ThermalMitigationAction int getThermalMitigationAction() {
+        return mThermalMitigationAction;
+    }
+
+    /**
+     * @return the data throttling request.
+     */
+    @Nullable
+    public DataThrottlingRequest getDataThrottlingRequest() {
+        return mDataThrottlingRequest;
+    }
+
+    public static final @NonNull Parcelable.Creator<ThermalMitigationRequest> CREATOR =
+            new Parcelable.Creator<ThermalMitigationRequest>() {
+
+        @Override
+        public ThermalMitigationRequest createFromParcel(Parcel in) {
+            return new ThermalMitigationRequest(in);
+        }
+
+        @Override
+        public ThermalMitigationRequest[] newArray(int size) {
+            return new ThermalMitigationRequest[size];
+        }
+    };
+
+    /**
+     * Provides a convenient way to set the fields of a {@link ThermalMitigationRequest} when
+     * creating a new instance.
+     *
+     * <p>The example below shows how you might create a new {@code ThermalMitigationRequest}:
+     *
+     * <pre><code>
+     *
+     * ThermalMitigationRequest dp = new ThermalMitigationRequest.Builder()
+     *     .setThermalMitigationAction(
+     *          ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING)
+     *     .setDataThrottlingRequest(new DataThrottlingRequest.Builder()
+     *          .setDataThrottlingAction(
+     *              DataThrottlingRequest.DATA_THROTTLING_ACTION_THROTTLE_SECONDARY_CARRIER)
+     *          .setCompletionDurationMillis(10000L)
+     *          .build())
+     *     .build();
+     * </code></pre>
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final class Builder {
+        private @ThermalMitigationAction int mThermalMitigationAction = -1;
+        private DataThrottlingRequest mDataThrottlingRequest;
+
+        /**
+         * Default constructor for Builder.
+         */
+        public Builder() {}
+
+        /**
+         * Set the thermal mitigation action.
+         *
+         * @param thermalMitigationAction thermal mitigation action. See {@link
+         *      #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}, {@link
+         *      #THERMAL_MITIGATION_ACTION_VOICE_ONLY}, and {@link
+         *      #THERMAL_MITIGATION_ACTION_RADIO_OFF} for more details.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setThermalMitigationAction(
+                @ThermalMitigationAction int thermalMitigationAction) {
+            mThermalMitigationAction = thermalMitigationAction;
+            return this;
+        }
+
+        /**
+         * Set the data throttling request.
+         *
+         * @param dataThrottlingRequest is the parameters for more fine-controlled data throttling.
+         *      This is only applicable if thermalMitigationAction is {@link
+         *      #THERMAL_MITIGATION_ACTION_DATA_THROTTLING}. Otherwise, it should not be set and
+         *      will throw an IllegalArgumentException if it is. See {@link DataThrottlingRequest}
+         *      for more details.
+         *
+         * @return The same instance of the builder.
+         */
+        public @NonNull Builder setDataThrottlingRequest(
+                @NonNull DataThrottlingRequest dataThrottlingRequest) {
+            mDataThrottlingRequest = dataThrottlingRequest;
+            return this;
+        }
+
+        /**
+         * Build the ThermalMitigationRequest.
+         *
+         * @return the ThermalMitigationRequest object.
+         */
+        public @NonNull ThermalMitigationRequest build() {
+            if (mThermalMitigationAction < 0) {
+                throw new IllegalArgumentException("thermalMitigationAction was "
+                        + " not set");
+            }
+
+            if (mThermalMitigationAction == THERMAL_MITIGATION_ACTION_DATA_THROTTLING) {
+                if (mDataThrottlingRequest == null) {
+                    throw new IllegalArgumentException("dataThrottlingRequest  cannot be null for "
+                            + "THERMAL_MITIGATION_ACTION_DATA_THROTTLING");
+                }
+
+
+            } else if (mDataThrottlingRequest != null) {
+                throw new IllegalArgumentException("dataThrottlingRequest must be null for "
+                        + "THERMAL_MITIGATION_ACTION_VOICE_ONLY and "
+                        + "THERMAL_MITIGATION_ACTION_RADIO_OFF");
+            }
+
+            return new ThermalMitigationRequest(mThermalMitigationAction, mDataThrottlingRequest);
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 69525a8..7e1aee7 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -36,6 +36,7 @@
 import android.telephony.CellIdentity;
 import android.telephony.CellInfo;
 import android.telephony.ClientRequestStats;
+import android.telephony.ThermalMitigationRequest;
 import android.telephony.IccOpenLogicalChannelResponse;
 import android.telephony.ICellInfoCallback;
 import android.telephony.ModemActivityInfo;
@@ -2254,4 +2255,14 @@
      * @return CarrierBandwidth with bandwidth of both primary and secondary carrier.
      */
     CarrierBandwidth getCarrierBandwidth(int subId);
+
+    /**
+     * Thermal mitigation request to control functionalities at modem.
+     *
+     * @param subId the id of the subscription
+     * @param thermalMitigationRequest holds the parameters necessary for the request.
+     * @throws InvalidThermalMitigationRequestException if the parametes are invalid.
+     */
+    int sendThermalMitigationRequest(int subId,
+            in ThermalMitigationRequest thermalMitigationRequest);
 }
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a2361a7..21cca4c 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -520,6 +520,7 @@
     int RIL_REQUEST_START_HANDOVER = 217;
     int RIL_REQUEST_CANCEL_HANDOVER = 218;
     int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
+    int RIL_REQUEST_SET_DATA_THROTTLING = 221;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;