Merge changes I28d7f1d9,Iea5090e4 into main

* changes:
  Critical temperature error notification
  External display management on temperature changes
diff --git a/core/res/res/drawable-nodpi/ic_thermostat_notification.xml b/core/res/res/drawable-nodpi/ic_thermostat_notification.xml
new file mode 100644
index 0000000..561c43d
--- /dev/null
+++ b/core/res/res/drawable-nodpi/ic_thermostat_notification.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2023 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="16"
+        android:viewportHeight="16">
+  <group>
+    <clip-path
+        android:pathData="M0,0h16v16h-16z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:fillType="evenOdd"
+        android:pathData="M8.9,7.1V5.75H12.5V7.1H8.9ZM8.9,4.4V3.05L14.3,3.05V4.4L8.9,4.4ZM5.3,14.3C4.3,14.3 3.45,13.95 2.75,13.25C2.05,12.55 1.7,11.7 1.7,10.7C1.7,10.075 1.837,9.5 2.112,8.975C2.4,8.45 2.787,8.031 3.275,7.719L3.275,3.725C3.275,3.162 3.469,2.688 3.856,2.3C4.256,1.9 4.738,1.7 5.3,1.7C5.863,1.7 6.338,1.9 6.725,2.3C7.125,2.688 7.325,3.162 7.325,3.725V7.719C7.813,8.031 8.194,8.45 8.469,8.975C8.756,9.5 8.9,10.075 8.9,10.7C8.9,11.7 8.55,12.55 7.85,13.25C7.15,13.95 6.3,14.3 5.3,14.3ZM3.05,10.7L7.55,10.7C7.55,10.387 7.481,10.094 7.344,9.819C7.219,9.531 7.031,9.281 6.781,9.069L5.975,8.45L5.975,3.725C5.975,3.537 5.906,3.381 5.769,3.256C5.644,3.119 5.488,3.05 5.3,3.05C5.113,3.05 4.95,3.119 4.813,3.256C4.688,3.381 4.625,3.537 4.625,3.725L4.625,8.45L3.838,9.069C3.588,9.294 3.394,9.55 3.256,9.837C3.119,10.125 3.05,10.413 3.05,10.7Z" />
+  </group>
+</vector>
diff --git a/core/res/res/drawable-nodpi/usb_cable_unknown_issue.xml b/core/res/res/drawable-nodpi/usb_cable_unknown_issue.xml
index dddad81..bcdbd6f4 100644
--- a/core/res/res/drawable-nodpi/usb_cable_unknown_issue.xml
+++ b/core/res/res/drawable-nodpi/usb_cable_unknown_issue.xml
@@ -16,12 +16,10 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="20"
-        android:viewportHeight="20">
+        android:viewportWidth="16"
+        android:viewportHeight="16">
     <path
-        android:pathData="M15.333,5.333V4.667C15.333,4.3 15.033,4 14.667,4L13.333,4C12.967,4 12.667,4.3 12.667,4.667V5.333H12V8C12,8.367 12.3,8.667 12.667,8.667H13.333L13.333,13.333C13.333,14.067 12.733,14.667 12,14.667C11.267,14.667 10.667,14.067 10.667,13.333L10.667,11.333V6.667C10.667,5.193 9.473,4 8,4C6.527,4 5.333,5.193 5.333,6.667L5.333,11.333H4.667C4.3,11.333 4,11.633 4,12L4,14.667H4.667V15.333C4.667,15.7 4.967,16 5.333,16H6.667C7.033,16 7.333,15.7 7.333,15.333V14.667H8L8,12C8,11.633 7.7,11.333 7.333,11.333H6.667L6.667,6.667C6.667,5.933 7.267,5.333 8,5.333C8.733,5.333 9.333,5.933 9.333,6.667V11.333L9.333,13.333C9.333,14.807 10.527,16 12,16C13.473,16 14.667,14.807 14.667,13.333L14.667,8.667H15.333C15.7,8.667 16,8.367 16,8V5.333H15.333Z"
+        android:pathData="M13.333,3.333V2.667C13.333,2.3 13.033,2 12.667,2L11.333,2C10.967,2 10.667,2.3 10.667,2.667V3.333H10V6C10,6.367 10.3,6.667 10.667,6.667H11.333L11.333,11.333C11.333,12.067 10.733,12.667 10,12.667C9.267,12.667 8.667,12.067 8.667,11.333L8.667,9.333V4.667C8.667,3.193 7.473,2 6,2C4.527,2 3.333,3.193 3.333,4.667L3.333,9.333H2.667C2.3,9.333 2,9.633 2,10L2,12.667H2.667V13.333C2.667,13.7 2.967,14 3.333,14H4.667C5.033,14 5.333,13.7 5.333,13.333V12.667H6L6,10C6,9.633 5.7,9.333 5.333,9.333H4.667L4.667,4.667C4.667,3.933 5.267,3.333 6,3.333C6.733,3.333 7.333,3.933 7.333,4.667L7.333,9.333L7.333,11.333C7.333,12.807 8.527,14 10,14C11.473,14 12.667,12.807 12.667,11.333L12.667,6.667H13.333C13.7,6.667 14,6.367 14,6V3.333H13.333Z"
         android:fillColor="#FFFFFFFF"
         android:fillType="evenOdd"/>
 </vector>
-
-
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a2a4e34f..15c188d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -6297,6 +6297,8 @@
     <string name="connected_display_unavailable_notification_title">Can\'t mirror to display</string>
     <!-- Content of connected display unavailable notification. [CHAR LIMIT=NONE] -->
     <string name="connected_display_unavailable_notification_content">Use a different cable and try again</string>
+    <!-- Content of connected display unavailable due to thermals notification. [CHAR LIMIT=NONE] -->
+    <string name="connected_display_thermally_unavailable_notification_content">Your device is too warm and can\'t mirror to the display until it cools down</string>
 
     <!-- Title of cable don't support displays notifications. [CHAR LIMIT=NONE] -->
     <string name="connected_display_cable_dont_support_displays_notification_title">Cable may not support displays</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2f3b510..e19d548 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2006,6 +2006,7 @@
   <java-symbol type="drawable" name="vpn_connected" />
   <java-symbol type="drawable" name="vpn_disconnected" />
   <java-symbol type="drawable" name="usb_cable_unknown_issue" />
+  <java-symbol type="drawable" name="ic_thermostat_notification" />
   <java-symbol type="id" name="ask_checkbox" />
   <java-symbol type="id" name="compat_checkbox" />
   <java-symbol type="id" name="original_app_icon" />
@@ -5085,6 +5086,7 @@
   <java-symbol type="array" name="device_state_notification_power_save_contents"/>
   <java-symbol type="string" name="connected_display_unavailable_notification_title"/>
   <java-symbol type="string" name="connected_display_unavailable_notification_content"/>
+  <java-symbol type="string" name="connected_display_thermally_unavailable_notification_content"/>
   <java-symbol type="string" name="connected_display_cable_dont_support_displays_notification_title"/>
   <java-symbol type="string" name="connected_display_cable_dont_support_displays_notification_content"/>
   <java-symbol type="string" name="concurrent_display_notification_name"/>
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 36fc4aa..eae153c 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -102,11 +102,11 @@
 import android.media.projection.IMediaProjectionManager;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
@@ -241,9 +241,6 @@
 
     private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
 
-    @VisibleForTesting
-    static final String ENABLE_ON_CONNECT =
-            "persist.sys.display.enable_on_connect.external";
     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
     // This value needs to be in sync with the threshold
     // in RefreshRateConfigs::getFrameRateDivisor.
@@ -266,6 +263,7 @@
     private final DisplayManagerHandler mHandler;
     private final Handler mUiHandler;
     private final DisplayModeDirector mDisplayModeDirector;
+    private final ExternalDisplayPolicy mExternalDisplayPolicy;
     private WindowManagerInternal mWindowManagerInternal;
     private InputManagerInternal mInputManagerInternal;
     private ActivityManagerInternal mActivityManagerInternal;
@@ -598,6 +596,7 @@
         mConfigParameterProvider = new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
         mExtraDisplayLoggingPackageName = DisplayProperties.debug_vri_package().orElse(null);
         mExtraDisplayEventLogging = !TextUtils.isEmpty(mExtraDisplayLoggingPackageName);
+        mExternalDisplayPolicy = new ExternalDisplayPolicy(new ExternalDisplayPolicyInjector());
     }
 
     public void setupSchedulerPolicies() {
@@ -667,6 +666,7 @@
             mDisplayModeDirector.onBootCompleted();
             mLogicalDisplayMapper.onBootCompleted();
             mDisplayNotificationManager.onBootCompleted();
+            mExternalDisplayPolicy.onBootCompleted();
         }
     }
 
@@ -1947,17 +1947,12 @@
         }
 
         setupLogicalDisplay(display);
-        // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
-        if (display.getDisplayInfoLocked().type == Display.TYPE_EXTERNAL) {
-            if ((Build.IS_ENG || Build.IS_USERDEBUG)
-                    && SystemProperties.getBoolean(ENABLE_ON_CONNECT, false)) {
-                Slog.w(TAG, "External display is enabled by default, bypassing user consent.");
-            } else {
-                display.setEnabledLocked(false);
-            }
-        }
 
-        sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);
+        if (ExternalDisplayPolicy.isExternalDisplay(display)) {
+            mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(display);
+        } else {
+            sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);
+        }
 
         updateLogicalDisplayState(display);
     }
@@ -3248,7 +3243,14 @@
 
     void enableConnectedDisplay(int displayId, boolean enabled) {
         synchronized (mSyncRoot) {
-            mLogicalDisplayMapper.setDisplayEnabledLocked(displayId, enabled);
+            final var logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId);
+            if (logicalDisplay == null) {
+                Slog.w(TAG, "enableConnectedDisplay: Can not find displayId=" + displayId);
+            } else if (ExternalDisplayPolicy.isExternalDisplay(logicalDisplay)) {
+                mExternalDisplayPolicy.setExternalDisplayEnabledLocked(logicalDisplay, enabled);
+            } else {
+                mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, enabled);
+            }
         }
     }
 
@@ -4470,22 +4472,12 @@
         @EnforcePermission(MANAGE_DISPLAYS)
         public void enableConnectedDisplay(int displayId) {
             enableConnectedDisplay_enforcePermission();
-            if (!mFlags.isConnectedDisplayManagementEnabled()) {
-                Slog.w(TAG, "External display management is not enabled on your device: "
-                                    + "cannot enable display.");
-                return;
-            }
             DisplayManagerService.this.enableConnectedDisplay(displayId, true);
         }
 
         @EnforcePermission(MANAGE_DISPLAYS)
         public void disableConnectedDisplay(int displayId) {
             disableConnectedDisplay_enforcePermission();
-            if (!mFlags.isConnectedDisplayManagementEnabled()) {
-                Slog.w(TAG, "External display management is not enabled on your device: "
-                                    + "cannot disable display.");
-                return;
-            }
             DisplayManagerService.this.enableConnectedDisplay(displayId, false);
         }
     }
@@ -5043,4 +5035,73 @@
          */
         long uptimeMillis();
     }
+
+    /**
+     * Implements necessary functionality for {@link ExternalDisplayPolicy}
+     */
+    private class ExternalDisplayPolicyInjector implements ExternalDisplayPolicy.Injector {
+        /**
+         * Sends event for the display.
+         */
+        @Override
+        public void sendExternalDisplayEventLocked(@NonNull final LogicalDisplay display,
+                @DisplayEvent int event) {
+            sendDisplayEventLocked(display, event);
+        }
+
+        /**
+         * Gets thermal service
+         */
+        @Override
+        @Nullable
+        public IThermalService getThermalService() {
+            return IThermalService.Stub.asInterface(ServiceManager.getService(
+                    Context.THERMAL_SERVICE));
+        }
+
+        /**
+         * @return display manager flags.
+         */
+        @Override
+        @NonNull
+        public DisplayManagerFlags getFlags() {
+            return mFlags;
+        }
+
+        /**
+         * @return Logical display mapper.
+         */
+        @Override
+        @NonNull
+        public LogicalDisplayMapper getLogicalDisplayMapper() {
+            return mLogicalDisplayMapper;
+        }
+
+        /**
+         * @return Sync root, for synchronization on this object across display manager.
+         */
+        @Override
+        @NonNull
+        public SyncRoot getSyncRoot() {
+            return mSyncRoot;
+        }
+
+        /**
+         * Notification manager for display manager
+         */
+        @Override
+        @NonNull
+        public DisplayNotificationManager getDisplayNotificationManager() {
+            return mDisplayNotificationManager;
+        }
+
+        /**
+         * Handler to use for notification sending to avoid requiring POST_NOTIFICATION permission.
+         */
+        @Override
+        @NonNull
+        public Handler getHandler() {
+            return mHandler;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/ExternalDisplayPolicy.java b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
new file mode 100644
index 0000000..dbe1e14
--- /dev/null
+++ b/services/core/java/com/android/server/display/ExternalDisplayPolicy.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2023 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.server.display;
+
+import static android.hardware.display.DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED;
+import static android.os.Temperature.THROTTLING_CRITICAL;
+import static android.os.Temperature.THROTTLING_NONE;
+import static android.view.Display.TYPE_EXTERNAL;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.display.DisplayManagerGlobal;
+import android.hardware.display.DisplayManagerGlobal.DisplayEvent;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.Temperature;
+import android.os.Temperature.ThrottlingStatus;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.display.DisplayManagerService.SyncRoot;
+import com.android.server.display.feature.DisplayManagerFlags;
+import com.android.server.display.notifications.DisplayNotificationManager;
+import com.android.server.display.utils.DebugUtils;
+
+/**
+ * Listens for Skin thermal sensor events, disables external displays if thermal status becomes
+ * equal or above {@link android.os.Temperature#THROTTLING_CRITICAL}, enables external displays if
+ * status goes below {@link android.os.Temperature#THROTTLING_CRITICAL}.
+ */
+class ExternalDisplayPolicy {
+    private static final String TAG = "ExternalDisplayPolicy";
+
+    // To enable these logs, run:
+    // 'adb shell setprop persist.log.tag.ExternalDisplayPolicy DEBUG && adb reboot'
+    private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
+
+    @VisibleForTesting
+    static final String ENABLE_ON_CONNECT = "persist.sys.display.enable_on_connect.external";
+
+    static boolean isExternalDisplay(@NonNull final LogicalDisplay logicalDisplay) {
+        return logicalDisplay.getDisplayInfoLocked().type == TYPE_EXTERNAL;
+    }
+
+    /**
+     * Injector interface for {@link ExternalDisplayPolicy}
+     */
+    interface Injector {
+        void sendExternalDisplayEventLocked(@NonNull LogicalDisplay display,
+                @DisplayEvent int event);
+
+        @NonNull
+        LogicalDisplayMapper getLogicalDisplayMapper();
+
+        @NonNull
+        SyncRoot getSyncRoot();
+
+        @Nullable
+        IThermalService getThermalService();
+
+        @NonNull
+        DisplayManagerFlags getFlags();
+
+        @NonNull
+        DisplayNotificationManager getDisplayNotificationManager();
+
+        @NonNull
+        Handler getHandler();
+    }
+
+    @NonNull
+    private final Injector mInjector;
+    @NonNull
+    private final LogicalDisplayMapper mLogicalDisplayMapper;
+    @NonNull
+    private final SyncRoot mSyncRoot;
+    @NonNull
+    private final DisplayManagerFlags mFlags;
+    @NonNull
+    private final DisplayNotificationManager mDisplayNotificationManager;
+    @NonNull
+    private final Handler mHandler;
+    @ThrottlingStatus
+    private volatile int mStatus = THROTTLING_NONE;
+
+    ExternalDisplayPolicy(@NonNull final Injector injector) {
+        mInjector = injector;
+        mLogicalDisplayMapper = mInjector.getLogicalDisplayMapper();
+        mSyncRoot = mInjector.getSyncRoot();
+        mFlags = mInjector.getFlags();
+        mDisplayNotificationManager = mInjector.getDisplayNotificationManager();
+        mHandler = mInjector.getHandler();
+    }
+
+    /**
+     * Starts listening for temperature changes.
+     */
+    void onBootCompleted() {
+        if (!mFlags.isConnectedDisplayManagementEnabled()) {
+            if (DEBUG) {
+                Slog.d(TAG, "External display management is not enabled on your device:"
+                                    + " cannot register thermal listener.");
+            }
+            return;
+        }
+
+        if (!mFlags.isConnectedDisplayErrorHandlingEnabled()) {
+            if (DEBUG) {
+                Slog.d(TAG, "ConnectedDisplayErrorHandlingEnabled is not enabled on your device:"
+                                    + " cannot register thermal listener.");
+            }
+            return;
+        }
+
+        if (!registerThermalServiceListener(new SkinThermalStatusObserver())) {
+            Slog.e(TAG, "Failed to register thermal listener");
+        }
+    }
+
+    /**
+     * Checks the display type is external, and if it is external then enables/disables it.
+     */
+    void setExternalDisplayEnabledLocked(@NonNull final LogicalDisplay logicalDisplay,
+            final boolean enabled) {
+        if (!isExternalDisplay(logicalDisplay)) {
+            Slog.e(TAG, "setExternalDisplayEnabledLocked called for non external display");
+            return;
+        }
+
+        if (!mFlags.isConnectedDisplayManagementEnabled()) {
+            if (DEBUG) {
+                Slog.d(TAG, "setExternalDisplayEnabledLocked: External display management is not"
+                                    + " enabled on your device, cannot enable/disable display.");
+            }
+            return;
+        }
+
+        if (enabled && !isExternalDisplayAllowed()) {
+            Slog.w(TAG, "setExternalDisplayEnabledLocked: External display can not be enabled"
+                                + " because it is currently not allowed.");
+            mHandler.post(mDisplayNotificationManager::onHighTemperatureExternalDisplayNotAllowed);
+            return;
+        }
+
+        mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, enabled);
+    }
+
+    /**
+     * Upon external display became available check if external displays allowed, this display
+     * is disabled and then sends {@link DisplayManagerGlobal#EVENT_DISPLAY_CONNECTED} to allow
+     * user to decide how to use this display.
+     */
+    void handleExternalDisplayConnectedLocked(@NonNull final LogicalDisplay logicalDisplay) {
+        if (!isExternalDisplay(logicalDisplay)) {
+            Slog.e(TAG, "handleExternalDisplayConnectedLocked called for non-external display");
+            return;
+        }
+
+        if (!mFlags.isConnectedDisplayManagementEnabled()) {
+            if (DEBUG) {
+                Slog.d(TAG, "handleExternalDisplayConnectedLocked connected display management"
+                                    + " flag is off");
+            }
+            return;
+        }
+
+        if ((Build.IS_ENG || Build.IS_USERDEBUG)
+                && SystemProperties.getBoolean(ENABLE_ON_CONNECT, false)) {
+            Slog.w(TAG, "External display is enabled by default, bypassing user consent.");
+            mInjector.sendExternalDisplayEventLocked(logicalDisplay, EVENT_DISPLAY_CONNECTED);
+            return;
+        } else {
+            // As external display is enabled by default, need to disable it now.
+            // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
+            logicalDisplay.setEnabledLocked(false);
+        }
+
+        if (!isExternalDisplayAllowed()) {
+            Slog.w(TAG, "handleExternalDisplayConnectedLocked: External display can not be used"
+                                + " because it is currently not allowed.");
+            mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+            return;
+        }
+
+        mInjector.sendExternalDisplayEventLocked(logicalDisplay, EVENT_DISPLAY_CONNECTED);
+
+        if (DEBUG) {
+            Slog.d(TAG, "handleExternalDisplayConnectedLocked complete"
+                                + " displayId=" + logicalDisplay.getDisplayIdLocked());
+        }
+    }
+
+    @GuardedBy("mSyncRoot")
+    private void disableExternalDisplayLocked(@NonNull final LogicalDisplay logicalDisplay) {
+        if (!isExternalDisplay(logicalDisplay)) {
+            return;
+        }
+
+        if (!mFlags.isConnectedDisplayManagementEnabled()) {
+            Slog.e(TAG, "disableExternalDisplayLocked shouldn't be called when the"
+                                + " connected display management flag is off");
+            return;
+        }
+
+        if (!mFlags.isConnectedDisplayErrorHandlingEnabled()) {
+            if (DEBUG) {
+                Slog.d(TAG, "disableExternalDisplayLocked shouldn't be called when the"
+                                    + " error handling flag is off");
+            }
+            return;
+        }
+
+        if (!logicalDisplay.isEnabledLocked()) {
+            if (DEBUG) {
+                Slog.d(TAG, "disableExternalDisplayLocked is not allowed:"
+                                    + " displayId=" + logicalDisplay.getDisplayIdLocked()
+                                    + " isEnabledLocked=false");
+            }
+            return;
+        }
+
+        if (!isExternalDisplayAllowed()) {
+            Slog.w(TAG, "External display is currently not allowed and is getting disabled.");
+            mDisplayNotificationManager.onHighTemperatureExternalDisplayNotAllowed();
+        }
+
+        mLogicalDisplayMapper.setDisplayEnabledLocked(logicalDisplay, /*enabled=*/ false);
+
+        if (DEBUG) {
+            Slog.d(TAG, "disableExternalDisplayLocked complete"
+                                + " displayId=" + logicalDisplay.getDisplayIdLocked());
+        }
+    }
+
+    /**
+     * @return whether external displays use is currently allowed.
+     */
+    @VisibleForTesting
+    boolean isExternalDisplayAllowed() {
+        return mStatus < THROTTLING_CRITICAL;
+    }
+
+    private boolean registerThermalServiceListener(
+            @NonNull final IThermalEventListener.Stub listener) {
+        final var thermalService = mInjector.getThermalService();
+        if (thermalService == null) {
+            Slog.w(TAG, "Could not observe thermal status. Service not available");
+            return false;
+        }
+        try {
+            thermalService.registerThermalEventListenerWithType(listener, Temperature.TYPE_SKIN);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Failed to register thermal status listener", e);
+            return false;
+        }
+        if (DEBUG) {
+            Slog.d(TAG, "registerThermalServiceListener complete.");
+        }
+        return true;
+    }
+
+    private void disableExternalDisplays() {
+        synchronized (mSyncRoot) {
+            mLogicalDisplayMapper.forEachLocked(this::disableExternalDisplayLocked);
+        }
+    }
+
+    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
+        @Override
+        public void notifyThrottling(@NonNull final Temperature temp) {
+            @ThrottlingStatus final int newStatus = temp.getStatus();
+            final var previousStatus = mStatus;
+            mStatus = newStatus;
+            if (THROTTLING_CRITICAL > previousStatus && THROTTLING_CRITICAL <= newStatus) {
+                disableExternalDisplays();
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index f3425d2e..115111a 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -1255,16 +1255,11 @@
         return null;
     }
 
-    void setDisplayEnabledLocked(int displayId, boolean enabled) {
-        LogicalDisplay display = getDisplayLocked(displayId);
-        if (display == null) {
-            Slog.w(TAG, "Cannot find display " + displayId);
-            return;
-        }
+    void setDisplayEnabledLocked(@NonNull LogicalDisplay display, boolean enabled) {
         boolean isEnabled = display.isEnabledLocked();
         if (isEnabled == enabled) {
             Slog.w(TAG, "Display is already " + (isEnabled ? "enabled" : "disabled") + ": "
-                    + displayId);
+                    + display.getDisplayIdLocked());
             return;
         }
         setEnabledLocked(display, enabled);
diff --git a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
index 5cdef38..f57bf29 100644
--- a/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
+++ b/services/core/java/com/android/server/display/notifications/DisplayNotificationManager.java
@@ -17,6 +17,7 @@
 package com.android.server.display.notifications;
 
 import static android.app.Notification.COLOR_DEFAULT;
+
 import static com.android.internal.notification.SystemNotificationChannels.ALERTS;
 
 import android.annotation.Nullable;
@@ -112,7 +113,8 @@
 
         sendErrorNotification(createErrorNotification(
                 R.string.connected_display_unavailable_notification_title,
-                R.string.connected_display_unavailable_notification_content));
+                R.string.connected_display_unavailable_notification_content,
+                R.drawable.usb_cable_unknown_issue));
     }
 
     /**
@@ -129,7 +131,8 @@
 
         sendErrorNotification(createErrorNotification(
                 R.string.connected_display_cable_dont_support_displays_notification_title,
-                R.string.connected_display_cable_dont_support_displays_notification_content));
+                R.string.connected_display_cable_dont_support_displays_notification_content,
+                R.drawable.usb_cable_unknown_issue));
     }
 
     /**
@@ -144,7 +147,24 @@
 
         sendErrorNotification(createErrorNotification(
                 R.string.connected_display_unavailable_notification_title,
-                R.string.connected_display_unavailable_notification_content));
+                R.string.connected_display_unavailable_notification_content,
+                R.drawable.usb_cable_unknown_issue));
+    }
+
+    /**
+     * Send notification about high temperature preventing usage of the external display.
+     */
+    public void onHighTemperatureExternalDisplayNotAllowed() {
+        if (!mConnectedDisplayErrorHandlingEnabled) {
+            Slog.d(TAG, "onHighTemperatureExternalDisplayNotAllowed:"
+                                + " mConnectedDisplayErrorHandlingEnabled is false");
+            return;
+        }
+
+        sendErrorNotification(createErrorNotification(
+                R.string.connected_display_unavailable_notification_title,
+                R.string.connected_display_thermally_unavailable_notification_content,
+                R.drawable.ic_thermostat_notification));
     }
 
     /**
@@ -176,7 +196,8 @@
     /**
      * @return a newly built notification about an issue with connected display.
      */
-    private Notification createErrorNotification(final int titleId, final int messageId) {
+    private Notification createErrorNotification(final int titleId, final int messageId,
+            final int icon) {
         final Resources resources = mContext.getResources();
         final CharSequence title = resources.getText(titleId);
         final CharSequence message = resources.getText(messageId);
@@ -190,7 +211,7 @@
 
         return new Notification.Builder(mContext, ALERTS)
                 .setGroup(NOTIFICATION_GROUP_NAME)
-                .setSmallIcon(R.drawable.usb_cable_unknown_issue)
+                .setSmallIcon(icon)
                 .setWhen(0)
                 .setTimeoutAfter(NOTIFICATION_TIMEOUT_MILLISEC)
                 .setOngoing(false)
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 3035258..9684f42 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -29,7 +29,7 @@
 import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
-import static com.android.server.display.DisplayManagerService.ENABLE_ON_CONNECT;
+import static com.android.server.display.ExternalDisplayPolicy.ENABLE_ON_CONNECT;
 import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
 
 import static com.google.common.truth.Truth.assertThat;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
new file mode 100644
index 0000000..fea431c
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/ExternalDisplayPolicyTest.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2023 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.server.display;
+
+import static android.hardware.display.DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED;
+import static android.view.Display.TYPE_EXTERNAL;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.IThermalEventListener;
+import android.os.IThermalService;
+import android.os.RemoteException;
+import android.os.Temperature;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.display.DisplayManagerService.SyncRoot;
+import com.android.server.display.feature.DisplayManagerFlags;
+import com.android.server.display.notifications.DisplayNotificationManager;
+import com.android.server.testutils.TestHandler;
+
+import com.google.testing.junit.testparameterinjector.TestParameter;
+import com.google.testing.junit.testparameterinjector.TestParameterInjector;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+
+/**
+ * Tests for {@link ExternalDisplayPolicy}
+ * Run: atest ExternalDisplayPolicyTest
+ */
+@SmallTest
+@RunWith(TestParameterInjector.class)
+public class ExternalDisplayPolicyTest {
+    private static final int EXTERNAL_DISPLAY_ID = 1;
+    private static final Temperature MODERATE_TEMPERATURE = new Temperature(/*value=*/ 40.5f,
+        /*type=*/ Temperature.TYPE_SKIN,
+        /*name=*/ "Test",
+        /*status=*/ Temperature.THROTTLING_MODERATE);
+    private static final Temperature SEVERE_TEMPERATURE = new Temperature(/*value=*/ 50.5f,
+        /*type=*/ Temperature.TYPE_SKIN,
+        /*name=*/ "Test",
+        /*status=*/ Temperature.THROTTLING_SEVERE);
+    private static final Temperature CRITICAL_TEMPERATURE = new Temperature(/*value=*/ 70.5f,
+            /*type=*/ Temperature.TYPE_SKIN,
+            /*name=*/ "Test",
+            /*status=*/ Temperature.THROTTLING_CRITICAL);
+    private static final Temperature EMERGENCY_TEMPERATURE = new Temperature(/*value=*/ 80.5f,
+            /*type=*/ Temperature.TYPE_SKIN,
+            /*name=*/ "Test",
+            /*status=*/ Temperature.THROTTLING_EMERGENCY);
+    @Mock
+    private ExternalDisplayPolicy.Injector mMockedInjector;
+    @Mock
+    private DisplayManagerFlags mMockedFlags;
+    @Mock
+    private LogicalDisplayMapper mMockedLogicalDisplayMapper;
+    @Mock
+    private IThermalService mMockedThermalService;
+    @Mock
+    private SyncRoot mMockedSyncRoot;
+    @Mock
+    private LogicalDisplay mMockedLogicalDisplay;
+    @Mock
+    private DisplayNotificationManager mMockedDisplayNotificationManager;
+    @Captor
+    private ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
+    @Captor
+    private ArgumentCaptor<Integer> mThermalEventTypeCaptor;
+    @Captor
+    private ArgumentCaptor<Consumer<LogicalDisplay>> mLogicalDisplayConsumerCaptor;
+    @Captor
+    private ArgumentCaptor<Boolean> mIsEnabledCaptor;
+    @Captor
+    private ArgumentCaptor<LogicalDisplay> mLogicalDisplayCaptor;
+    @Captor
+    private ArgumentCaptor<Integer> mDisplayEventCaptor;
+    private ExternalDisplayPolicy mExternalDisplayPolicy;
+    private TestHandler mHandler;
+
+    /** Setup tests. */
+    @Before
+    public void setup() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mHandler = new TestHandler(/*callback=*/ null);
+        when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+        when(mMockedFlags.isConnectedDisplayErrorHandlingEnabled()).thenReturn(true);
+        when(mMockedInjector.getFlags()).thenReturn(mMockedFlags);
+        when(mMockedInjector.getLogicalDisplayMapper()).thenReturn(mMockedLogicalDisplayMapper);
+        when(mMockedInjector.getThermalService()).thenReturn(mMockedThermalService);
+        when(mMockedInjector.getSyncRoot()).thenReturn(mMockedSyncRoot);
+        when(mMockedInjector.getDisplayNotificationManager()).thenReturn(
+                mMockedDisplayNotificationManager);
+        when(mMockedInjector.getHandler()).thenReturn(mHandler);
+        mExternalDisplayPolicy = new ExternalDisplayPolicy(mMockedInjector);
+
+        // Initialize mocked logical display
+        when(mMockedLogicalDisplay.getDisplayIdLocked()).thenReturn(EXTERNAL_DISPLAY_ID);
+        when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(true);
+        final var mockedLogicalDisplayInfo = new DisplayInfo();
+        mockedLogicalDisplayInfo.type = TYPE_EXTERNAL;
+        when(mMockedLogicalDisplay.getDisplayInfoLocked()).thenReturn(mockedLogicalDisplayInfo);
+        when(mMockedLogicalDisplayMapper.getDisplayLocked(EXTERNAL_DISPLAY_ID)).thenReturn(
+                mMockedLogicalDisplay);
+    }
+
+    @Test
+    public void testTryEnableExternalDisplay_criticalThermalCondition() throws RemoteException {
+        // Disallow external displays due to thermals.
+        setTemperature(registerThermalListener(), List.of(CRITICAL_TEMPERATURE));
+        assertIsExternalDisplayAllowed(/*enabled=*/ false);
+        assertDisplaySetEnabled(/*enabled=*/ false);
+
+        // Check that display can not be enabled with tryEnableExternalDisplay.
+        mExternalDisplayPolicy.setExternalDisplayEnabledLocked(mMockedLogicalDisplay,
+                /*enabled=*/ true);
+        mHandler.flush();
+        verify(mMockedLogicalDisplayMapper, never()).setDisplayEnabledLocked(any(), anyBoolean());
+        verify(mMockedDisplayNotificationManager, times(2))
+                .onHighTemperatureExternalDisplayNotAllowed();
+    }
+
+    @Test
+    public void testTryEnableExternalDisplay_featureDisabled(@TestParameter final boolean enable) {
+        when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(false);
+        mExternalDisplayPolicy.setExternalDisplayEnabledLocked(mMockedLogicalDisplay, enable);
+        mHandler.flush();
+        verify(mMockedLogicalDisplayMapper, never()).setDisplayEnabledLocked(any(), anyBoolean());
+        verify(mMockedDisplayNotificationManager, never())
+                .onHighTemperatureExternalDisplayNotAllowed();
+    }
+
+    @Test
+    public void testTryDisableExternalDisplay_criticalThermalCondition() throws RemoteException {
+        // Disallow external displays due to thermals.
+        setTemperature(registerThermalListener(), List.of(CRITICAL_TEMPERATURE));
+        assertIsExternalDisplayAllowed(/*enabled=*/ false);
+        assertDisplaySetEnabled(/*enabled=*/ false);
+
+        // Check that display can be disabled with tryEnableExternalDisplay.
+        mExternalDisplayPolicy.setExternalDisplayEnabledLocked(mMockedLogicalDisplay,
+                /*enabled=*/ false);
+        mHandler.flush();
+        assertDisplaySetEnabled(/*enabled=*/ false);
+        // Expected only 1 invocation, upon critical temperature.
+        verify(mMockedDisplayNotificationManager).onHighTemperatureExternalDisplayNotAllowed();
+    }
+
+    @Test
+    public void testSetEnabledExternalDisplay(@TestParameter final boolean enable) {
+        mExternalDisplayPolicy.setExternalDisplayEnabledLocked(mMockedLogicalDisplay, enable);
+        assertDisplaySetEnabled(enable);
+    }
+
+    @Test
+    public void testOnExternalDisplayAvailable() {
+        when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(false);
+        mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay);
+        assertAskedToEnableDisplay();
+    }
+
+    @Test
+    public void testOnExternalDisplayAvailable_criticalThermalCondition()
+            throws RemoteException {
+        // Disallow external displays due to thermals.
+        setTemperature(registerThermalListener(), List.of(CRITICAL_TEMPERATURE));
+        assertIsExternalDisplayAllowed(/*enabled=*/ false);
+        assertDisplaySetEnabled(/*enabled=*/ false);
+
+        when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(false);
+        mExternalDisplayPolicy.handleExternalDisplayConnectedLocked(mMockedLogicalDisplay);
+        verify(mMockedInjector, never()).sendExternalDisplayEventLocked(any(), anyInt());
+        verify(mMockedDisplayNotificationManager, times(2))
+                .onHighTemperatureExternalDisplayNotAllowed();
+    }
+
+    @Test
+    public void testNoThermalListenerRegistered_featureDisabled(
+            @TestParameter final boolean isConnectedDisplayManagementEnabled,
+            @TestParameter final boolean isErrorHandlingEnabled) throws RemoteException {
+        assumeFalse(isConnectedDisplayManagementEnabled && isErrorHandlingEnabled);
+        when(mMockedFlags.isConnectedDisplayManagementEnabled()).thenReturn(
+                isConnectedDisplayManagementEnabled);
+        when(mMockedFlags.isConnectedDisplayErrorHandlingEnabled()).thenReturn(
+                isErrorHandlingEnabled);
+
+        mExternalDisplayPolicy.onBootCompleted();
+        verify(mMockedThermalService, never()).registerThermalEventListenerWithType(
+                any(), anyInt());
+    }
+
+    @Test
+    public void testOnCriticalTemperature_disallowAndAllowExternalDisplay() throws RemoteException {
+        final var thermalListener = registerThermalListener();
+
+        setTemperature(thermalListener, List.of(CRITICAL_TEMPERATURE, EMERGENCY_TEMPERATURE));
+        assertIsExternalDisplayAllowed(/*enabled=*/ false);
+        assertDisplaySetEnabled(false);
+
+        thermalListener.notifyThrottling(SEVERE_TEMPERATURE);
+        thermalListener.notifyThrottling(MODERATE_TEMPERATURE);
+        assertIsExternalDisplayAllowed(/*enabled=*/ true);
+        verify(mMockedLogicalDisplayMapper, never()).forEachLocked(any());
+    }
+
+    private void setTemperature(final IThermalEventListener thermalEventListener,
+            final List<Temperature> temperature) throws RemoteException {
+        for (var t : temperature) {
+            thermalEventListener.notifyThrottling(t);
+        }
+        verify(mMockedLogicalDisplayMapper).forEachLocked(mLogicalDisplayConsumerCaptor.capture());
+        mLogicalDisplayConsumerCaptor.getValue().accept(mMockedLogicalDisplay);
+    }
+
+    private void assertDisplaySetEnabled(final boolean enabled) {
+        // Check setDisplayEnabledLocked is triggered to disable display.
+        verify(mMockedLogicalDisplayMapper).setDisplayEnabledLocked(
+                mLogicalDisplayCaptor.capture(), mIsEnabledCaptor.capture());
+        assertThat(mLogicalDisplayCaptor.getValue()).isEqualTo(mMockedLogicalDisplay);
+        assertThat(mIsEnabledCaptor.getValue()).isEqualTo(enabled);
+        clearInvocations(mMockedLogicalDisplayMapper);
+        when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(enabled);
+    }
+
+    private void assertAskedToEnableDisplay() {
+        // Check sendExternalDisplayEventLocked is triggered when display can be enabled.
+        verify(mMockedInjector).sendExternalDisplayEventLocked(mLogicalDisplayCaptor.capture(),
+                mDisplayEventCaptor.capture());
+        assertThat(mLogicalDisplayCaptor.getValue()).isEqualTo(mMockedLogicalDisplay);
+        assertThat(mDisplayEventCaptor.getValue()).isEqualTo(EVENT_DISPLAY_CONNECTED);
+        clearInvocations(mMockedLogicalDisplayMapper);
+        when(mMockedLogicalDisplay.isEnabledLocked()).thenReturn(true);
+    }
+
+    private void assertIsExternalDisplayAllowed(final boolean enabled) {
+        assertThat(mExternalDisplayPolicy.isExternalDisplayAllowed()).isEqualTo(enabled);
+    }
+
+    private IThermalEventListener registerThermalListener() throws RemoteException {
+        // Initialize and register thermal listener
+        mExternalDisplayPolicy.onBootCompleted();
+        verify(mMockedThermalService).registerThermalEventListenerWithType(
+                mThermalEventListenerCaptor.capture(), mThermalEventTypeCaptor.capture());
+        final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
+        assertThat(listener).isNotNull();
+        assertThat(mThermalEventTypeCaptor.getValue()).isEqualTo(Temperature.TYPE_SKIN);
+        return listener;
+    }
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
index 8b13018..43d2b8f 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -346,14 +346,14 @@
 
         // Disable device
         mLogicalDisplayMapper.setDisplayEnabledLocked(
-                displayAdded.getDisplayIdLocked(), /* isEnabled= */ false);
+                displayAdded, /* isEnabled= */ false);
         verify(mListenerMock).onLogicalDisplayEventLocked(mDisplayCaptor.capture(),
                 eq(LOGICAL_DISPLAY_EVENT_REMOVED));
         clearInvocations(mListenerMock);
 
         // Enable device
         mLogicalDisplayMapper.setDisplayEnabledLocked(
-                displayAdded.getDisplayIdLocked(), /* isEnabled= */ true);
+                displayAdded, /* isEnabled= */ true);
         verify(mListenerMock).onLogicalDisplayEventLocked(mDisplayCaptor.capture(),
                 eq(LOGICAL_DISPLAY_EVENT_ADDED));
     }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
index 1d2034b..4efd15c 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/notifications/DisplayNotificationManagerTest.java
@@ -75,6 +75,14 @@
     }
 
     @Test
+    public void testNotificationOnHighTemperatureExternalDisplayNotAllowed() {
+        var dnm = createDisplayNotificationManager(/*isNotificationManagerAvailable=*/ true,
+                /*isErrorHandlingEnabled=*/ true);
+        dnm.onHighTemperatureExternalDisplayNotAllowed();
+        assertExpectedNotification();
+    }
+
+    @Test
     public void testNotificationOnHotplugConnectionError() {
         var dnm = createDisplayNotificationManager(/*isNotificationManagerAvailable=*/ true,
                 /*isErrorHandlingEnabled=*/ true);
@@ -112,6 +120,7 @@
         dnm.onHotplugConnectionError();
         dnm.onDisplayPortLinkTrainingFailure();
         dnm.onCableNotCapableDisplayPort();
+        dnm.onHighTemperatureExternalDisplayNotAllowed();
         verify(mMockedNotificationManager, never()).notify(anyString(), anyInt(), any());
     }