Add driving state transition log to dumpsys.

Add a way to log transitions from one state to another for different
pieces of the car service to use.

Bug: 79547680
Test: adb shell dumpsys activity service com.android.car

Change-Id: I57825492114460ad3db96372bee97a3d0fec622e
diff --git a/service/src/com/android/car/CarUxRestrictionsManagerService.java b/service/src/com/android/car/CarUxRestrictionsManagerService.java
index 823075e..289706d 100644
--- a/service/src/com/android/car/CarUxRestrictionsManagerService.java
+++ b/service/src/com/android/car/CarUxRestrictionsManagerService.java
@@ -36,6 +36,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -46,6 +47,7 @@
         CarServiceBase {
     private static final String TAG = "CarUxR";
     private static final boolean DBG = false;
+    private static final int MAX_TRANSITION_LOG_SIZE = 20;
     private final Context mContext;
     private final CarDrivingStateService mDrivingStateService;
     private final CarSensorService mCarSensorService;
@@ -55,6 +57,9 @@
     private CarUxRestrictions mCurrentUxRestrictions;
     private float mCurrentMovingSpeed;
     private boolean mFallbackToDefaults;
+    // For dumpsys logging
+    private final LinkedList<Utils.TransitionLog> mTransitionLogs = new LinkedList<>();
+
 
     public CarUxRestrictionsManagerService(Context context, CarDrivingStateService drvService,
             CarSensorService sensorService) {
@@ -244,6 +249,10 @@
                 "Requires DO? " + mCurrentUxRestrictions.isRequiresDistractionOptimization());
         writer.println("Current UXR: " + mCurrentUxRestrictions.getActiveRestrictions());
         mHelper.dump(writer);
+        writer.println("UX Restriction change log:");
+        for (Utils.TransitionLog tlog : mTransitionLogs) {
+            writer.println(tlog);
+        }
     }
 
     /**
@@ -355,6 +364,17 @@
             // Ignore dispatching if the restrictions has not changed.
             return;
         }
+        // for dumpsys logging
+        StringBuilder extraInfo = new StringBuilder();
+        extraInfo.append(
+                mCurrentUxRestrictions.isRequiresDistractionOptimization() ? "DO -> "
+                        : "No DO -> ");
+        extraInfo.append(
+                uxRestrictions.isRequiresDistractionOptimization() ? "DO" : "No DO");
+        addTransitionLog(TAG, mCurrentUxRestrictions.getActiveRestrictions(),
+                uxRestrictions.getActiveRestrictions(), System.currentTimeMillis(),
+                extraInfo.toString());
+
         mCurrentUxRestrictions = uxRestrictions;
         if (DBG) {
             Log.d(TAG, "dispatching to " + mUxRClients.size() + " clients");
@@ -382,4 +402,14 @@
         }
         return mHelper.createUxRestrictionsEvent(requiresOpt, restrictions);
     }
+
+    private void addTransitionLog(String name, int from, int to, long timestamp, String extra) {
+        if (mTransitionLogs.size() >= MAX_TRANSITION_LOG_SIZE) {
+            mTransitionLogs.remove();
+        }
+
+        Utils.TransitionLog tLog = new Utils.TransitionLog(name, from, to, timestamp, extra);
+        mTransitionLogs.add(tLog);
+    }
+
 }