Merge "Add a binder cache to UiModeManager#getCurrentModeType" into main
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 7903f1c..2e6f3e1 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import static android.app.Flags.enableCurrentModeTypeBinderCache;
 import static android.app.Flags.enableNightModeBinderCache;
 
 import android.annotation.CallbackExecutor;
@@ -682,6 +683,53 @@
         }
     }
 
+    private Integer getCurrentModeTypeFromServer() {
+        try {
+            if (sGlobals != null) {
+                return sGlobals.mService.getCurrentModeType();
+            }
+            return Configuration.UI_MODE_TYPE_NORMAL;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+
+    /**
+     * Retrieve the current running mode type for the user.
+     */
+    private final IpcDataCache.QueryHandler<Void, Integer> mCurrentModeTypeQuery =
+            new IpcDataCache.QueryHandler<>() {
+
+                @Override
+                @NonNull
+                public Integer apply(Void query) {
+                    return getCurrentModeTypeFromServer();
+                }
+            };
+
+    private static final String CURRENT_MODE_TYPE_API = "getCurrentModeType";
+
+    /**
+     * Cache the current running mode type for a user.
+     */
+    private final IpcDataCache<Void, Integer> mCurrentModeTypeCache =
+            new IpcDataCache<>(1, IpcDataCache.MODULE_SYSTEM,
+                    CURRENT_MODE_TYPE_API, /* cacheName= */ "CurrentModeTypeCache",
+                    mCurrentModeTypeQuery);
+
+    /**
+     * Invalidate the current mode type cache.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_CURRENT_MODE_TYPE_BINDER_CACHE)
+    public static void invalidateCurrentModeTypeCache() {
+        IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM,
+                CURRENT_MODE_TYPE_API);
+    }
+
+
     /**
      * Return the current running mode type.  May be one of
      * {@link Configuration#UI_MODE_TYPE_NORMAL Configuration.UI_MODE_TYPE_NORMAL},
@@ -693,14 +741,11 @@
      * {@link Configuration#UI_MODE_TYPE_VR_HEADSET Configuration.UI_MODE_TYPE_VR_HEADSET}.
      */
     public int getCurrentModeType() {
-        if (sGlobals != null) {
-            try {
-                return sGlobals.mService.getCurrentModeType();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        if (enableCurrentModeTypeBinderCache()) {
+            return mCurrentModeTypeCache.query(null);
+        } else {
+            return getCurrentModeTypeFromServer();
         }
-        return Configuration.UI_MODE_TYPE_NORMAL;
     }
 
     /**
diff --git a/core/java/android/app/ui_mode_manager.aconfig b/core/java/android/app/ui_mode_manager.aconfig
index 9f44a4d..05b46e0 100644
--- a/core/java/android/app/ui_mode_manager.aconfig
+++ b/core/java/android/app/ui_mode_manager.aconfig
@@ -9,4 +9,15 @@
      metadata {
          purpose: PURPOSE_BUGFIX
      }
+}
+
+flag {
+     namespace: "systemui"
+     name: "enable_current_mode_type_binder_cache"
+     description: "Enables the use of binder caching for current running mode type."
+     bug: "362572732"
+     is_fixed_read_only: true
+     metadata {
+         purpose: PURPOSE_BUGFIX
+     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index f32031de..7daf158 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.app.Flags.modesApi;
+import static android.app.Flags.enableCurrentModeTypeBinderCache;
 import static android.app.Flags.enableNightModeBinderCache;
 import static android.app.UiModeManager.ContrastUtils.CONTRAST_DEFAULT_VALUE;
 import static android.app.UiModeManager.DEFAULT_PRIORITY;
@@ -138,7 +139,7 @@
 
     private int mLastBroadcastState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
-    private final NightMode mNightMode = new NightMode(){
+    private final IntProperty mNightMode = new IntProperty(){
         private int mNightModeValue = UiModeManager.MODE_NIGHT_NO;
 
         @Override
@@ -192,7 +193,22 @@
     // flag set by resource, whether to night mode change for normal all or not.
     private boolean mNightModeLocked = false;
 
-    int mCurUiMode = 0;
+    private final IntProperty mCurUiMode = new IntProperty(){
+        private int mCurrentModeTypeValue = 0;
+
+        @Override
+        public int get() {
+            return mCurrentModeTypeValue;
+        }
+
+        @Override
+        public void set(int mode) {
+            mCurrentModeTypeValue = mode;
+            if (enableCurrentModeTypeBinderCache()) {
+                UiModeManager.invalidateCurrentModeTypeCache();
+            }
+        }
+    };
     private int mSetUiMode = 0;
     private boolean mHoldingConfiguration = false;
     private int mCurrentUser;
@@ -810,7 +826,7 @@
             final long ident = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    return mCurUiMode & Configuration.UI_MODE_TYPE_MASK;
+                    return mCurUiMode.get() & Configuration.UI_MODE_TYPE_MASK;
                 }
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -1492,7 +1508,7 @@
             pw.print(" mCarModeEnableFlags="); pw.print(mCarModeEnableFlags);
             pw.print(" mEnableCarDockLaunch="); pw.println(mEnableCarDockLaunch);
 
-            pw.print("  mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode));
+            pw.print("  mCurUiMode=0x"); pw.print(Integer.toHexString(mCurUiMode.get()));
             pw.print(" mUiModeLocked="); pw.print(mUiModeLocked);
             pw.print(" mSetUiMode=0x"); pw.println(Integer.toHexString(mSetUiMode));
 
@@ -1745,7 +1761,7 @@
                     + "; uiMode=" + uiMode);
         }
 
-        mCurUiMode = uiMode;
+        mCurUiMode.set(uiMode);
         if (!mHoldingConfiguration && (!mWaitForDeviceInactive || mPowerSave)) {
             mConfiguration.uiMode = uiMode;
         }
@@ -1892,7 +1908,7 @@
         boolean keepScreenOn = mCharging &&
                 ((mCarModeEnabled && mCarModeKeepsScreenOn &&
                 (mCarModeEnableFlags & UiModeManager.ENABLE_CAR_MODE_ALLOW_SLEEP) == 0) ||
-                (mCurUiMode == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
+                (mCurUiMode.get() == Configuration.UI_MODE_TYPE_DESK && mDeskModeKeepsScreenOn));
         if (keepScreenOn != mWakeLock.isHeld()) {
             if (keepScreenOn) {
                 mWakeLock.acquire();
@@ -2319,11 +2335,12 @@
     }
 
     /**
-     * Interface to contain the value for system night mode. We make the night mode accessible
-     * through this class to ensure that the reassignment of this value invalidates the cache.
+     * Interface to contain the value for an integral property. We make the property
+     * accessible through this class to ensure that the reassignment of this value invalidates the
+     * cache.
      */
-    private interface NightMode {
+    private interface IntProperty {
         int get();
-        void set(int mode);
+        void set(int value);
     }
 }