@@ -40,6 +40,8 @@ public class SignalService extends Service {
4040 private static final long HAZARD_TRIGGER_COOLDOWN_MS = 30_000L ;
4141
4242 private static final int TURN_PROP_ID = 0x21409326 ;
43+ private static final int HAZARD_LIGHTS_STATE_PROP_ID = 0x11400e03 ;
44+ private static final int HAZARD_LIGHTS_SWITCH_PROP_ID = 0x11400e13 ;
4345 private static final int REVERSE_GEAR_VALUE = 2 ;
4446 private static final String OEM_AVM_PACKAGE = "com.saicmotor.hmi.aroundview" ;
4547 public static final String ACTION_ROUTE_CAMERA = "com.drivehub.kamera.ACTION_ROUTE_CAMERA" ;
@@ -129,6 +131,15 @@ public static String getCurrentTurnLampDebugText() {
129131 }
130132 }
131133
134+ public static String getCurrentHazardDebugText (Context context ) {
135+ SignalService inst = sInstance ;
136+ if (inst != null ) {
137+ return inst .readHazardDebugText ();
138+ }
139+ return buildHazardDebugText (readHazardPropertyValue (context , null , HAZARD_LIGHTS_STATE_PROP_ID ),
140+ readHazardPropertyValue (context , null , HAZARD_LIGHTS_SWITCH_PROP_ID ));
141+ }
142+
132143 @ Override
133144 public void onCreate () {
134145 super .onCreate ();
@@ -259,6 +270,56 @@ private int readIntMethod(Object target, String methodName, int def) {
259270 return def ;
260271 }
261272
273+ private String readHazardDebugText () {
274+ return buildHazardDebugText (
275+ readHazardPropertyValue (this , car , HAZARD_LIGHTS_STATE_PROP_ID ),
276+ readHazardPropertyValue (this , car , HAZARD_LIGHTS_SWITCH_PROP_ID )
277+ );
278+ }
279+
280+ private static String buildHazardDebugText (Integer stateValue , Integer switchValue ) {
281+ return "state=" + formatHazardDebugValue (stateValue ) + " switch=" + formatHazardDebugValue (switchValue );
282+ }
283+
284+ private static String formatHazardDebugValue (Integer value ) {
285+ return value == null ? "null" : String .valueOf (value );
286+ }
287+
288+ private static Integer readHazardPropertyValue (Context context , Object existingCar , int propertyId ) {
289+ Object localCar = existingCar ;
290+ boolean disconnectAfterRead = false ;
291+ try {
292+ if (localCar == null ) {
293+ Class <?> carClass = Class .forName ("android.car.Car" );
294+ Method createCar = carClass .getMethod ("createCar" , Context .class );
295+ localCar = createCar .invoke (null , context );
296+ if (localCar == null ) return null ;
297+ Method connect = carClass .getMethod ("connect" );
298+ connect .invoke (localCar );
299+ disconnectAfterRead = true ;
300+ }
301+
302+ Method getCarManager = localCar .getClass ().getMethod ("getCarManager" , String .class );
303+ Object propertyManager = getCarManager .invoke (localCar , "property" );
304+ if (propertyManager == null ) return null ;
305+
306+ Method getProperty = propertyManager .getClass ().getMethod (
307+ "getProperty" , Class .class , int .class , int .class );
308+ Object value = getProperty .invoke (propertyManager , Integer .class , propertyId , 0 );
309+ return value instanceof Integer ? (Integer ) value : null ;
310+ } catch (Throwable ignored ) {
311+ return null ;
312+ } finally {
313+ if (disconnectAfterRead && localCar != null ) {
314+ try {
315+ Method disconnect = localCar .getClass ().getMethod ("disconnect" );
316+ disconnect .invoke (localCar );
317+ } catch (Throwable ignored ) {
318+ }
319+ }
320+ }
321+ }
322+
262323 private void updateOverlayDecision () {
263324 // Skip work if nothing changed.
264325 if (currentLamp == lastLamp && currentGear == readCachedGear ()) {
0 commit comments