@@ -72,6 +72,8 @@ public class OverlayService extends Service implements TextureView.SurfaceTextur
7272 (sharedPreferences , key ) -> {
7373 if (UiPrefs .KEY_TILE_CORNER_RADIUS .equals (key )) {
7474 applyOverlayCornerRadius ();
75+ } else if (UiPrefs .KEY_OVERLAY_ROTATE_TO_DRIVING_DIRECTION .equals (key )) {
76+ updateOverlayPresentation (true );
7577 }
7678 };
7779
@@ -114,6 +116,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
114116 showFloatingWindow ();
115117 } else {
116118 applyOverlayCornerRadius ();
119+ updateOverlayPresentation (false );
117120 // If the overlay is already open and only the camera index changed, switch the feed.
118121 if (textureSurface != null && textureSurface .isValid ()) {
119122 startPreview ();
@@ -139,6 +142,7 @@ private void showFloatingWindow() {
139142 }
140143 } catch (Throwable ignored ) {
141144 }
145+ normalizeOverlaySizeForCurrentMode ();
142146
143147 overlayParams = new WindowManager .LayoutParams (
144148 overlayWidthPx ,
@@ -181,6 +185,7 @@ public boolean onScale(ScaleGestureDetector detector) {
181185 overlayParams .height = overlayHeightPx ;
182186 clampOverlayPositionToScreen ();
183187 windowManager .updateViewLayout (overlayView , overlayParams );
188+ applyPreviewTransform ();
184189 return true ;
185190 }
186191
@@ -191,6 +196,7 @@ public void onScaleEnd(ScaleGestureDetector detector) {
191196 });
192197
193198 windowManager .addView (overlayView , overlayParams );
199+ applyPreviewTransform ();
194200
195201 overlayView .setOnTouchListener ((v , event ) -> {
196202 // Two fingers: pinch to resize, with no dragging.
@@ -299,9 +305,9 @@ private int dpToPx(int dp) {
299305 return Math .round (dp * getResources ().getDisplayMetrics ().density );
300306 }
301307
302- /** Keeps the 1000:480 aspect ratio while clamping size to screen and min/max bounds. */
308+ /** Keeps the active overlay aspect ratio while clamping size to screen and min/max bounds. */
303309 private int [] clampOverlaySize (int w ) {
304- float aspect = ( float ) DEFAULT_OVERLAY_WIDTH_PX / ( float ) DEFAULT_OVERLAY_HEIGHT_PX ;
310+ float aspect = getActiveOverlayAspect () ;
305311 int maxW = OVERLAY_MAX_WIDTH_PX ;
306312 int maxH = OVERLAY_MAX_WIDTH_PX ;
307313 int [] screenSize = getAvailableScreenSizePx ();
@@ -330,6 +336,79 @@ private int[] clampOverlaySize(int w) {
330336 return new int []{w , h };
331337 }
332338
339+ private void normalizeOverlaySizeForCurrentMode () {
340+ boolean shouldRotate = shouldRotatePreviewToDrivingDirection ();
341+ boolean isLandscape = overlayWidthPx >= overlayHeightPx ;
342+ if (shouldRotate == isLandscape ) {
343+ int swappedWidth = overlayHeightPx ;
344+ overlayHeightPx = overlayWidthPx ;
345+ overlayWidthPx = swappedWidth ;
346+ }
347+ int [] clamped = clampOverlaySize (overlayWidthPx );
348+ overlayWidthPx = clamped [0 ];
349+ overlayHeightPx = clamped [1 ];
350+ }
351+
352+ private float getActiveOverlayAspect () {
353+ return shouldRotatePreviewToDrivingDirection ()
354+ ? (float ) DEFAULT_OVERLAY_HEIGHT_PX / (float ) DEFAULT_OVERLAY_WIDTH_PX
355+ : (float ) DEFAULT_OVERLAY_WIDTH_PX / (float ) DEFAULT_OVERLAY_HEIGHT_PX ;
356+ }
357+
358+ private boolean shouldRotatePreviewToDrivingDirection () {
359+ return uiPrefs != null
360+ && UiPrefs .isOverlayRotationToDrivingDirectionEnabled (uiPrefs )
361+ && (cameraIndex == 14 || cameraIndex == 16 );
362+ }
363+
364+ private float getPreviewRotationDegrees () {
365+ if (!shouldRotatePreviewToDrivingDirection ()) {
366+ return 0f ;
367+ }
368+ return cameraIndex == 16 ? -90f : 90f ;
369+ }
370+
371+ private void updateOverlayPresentation (boolean persist ) {
372+ normalizeOverlaySizeForCurrentMode ();
373+ if (overlayParams != null ) {
374+ overlayParams .width = overlayWidthPx ;
375+ overlayParams .height = overlayHeightPx ;
376+ clampOverlayPositionToScreen ();
377+ if (windowManager != null && overlayView != null ) {
378+ windowManager .updateViewLayout (overlayView , overlayParams );
379+ }
380+ }
381+ applyPreviewTransform ();
382+ if (persist ) {
383+ saveOverlayLayoutPrefs ();
384+ }
385+ }
386+
387+ private void applyPreviewTransform () {
388+ if (textureView == null ) return ;
389+ textureView .post (() -> {
390+ if (textureView == null ) return ;
391+ FrameLayout .LayoutParams params ;
392+ if (shouldRotatePreviewToDrivingDirection ()) {
393+ params = new FrameLayout .LayoutParams (
394+ overlayHeightPx ,
395+ overlayWidthPx ,
396+ Gravity .CENTER
397+ );
398+ } else {
399+ params = new FrameLayout .LayoutParams (
400+ ViewGroup .LayoutParams .MATCH_PARENT ,
401+ ViewGroup .LayoutParams .MATCH_PARENT ,
402+ Gravity .CENTER
403+ );
404+ }
405+ textureView .setLayoutParams (params );
406+ textureView .setScaleX (1f );
407+ textureView .setScaleY (1f );
408+ textureView .setRotation (getPreviewRotationDegrees ());
409+ });
410+ }
411+
333412 private void clampOverlayPositionToScreen () {
334413 if (windowManager == null || overlayParams == null ) return ;
335414 int [] screenSize = getAvailableScreenSizePx ();
@@ -413,12 +492,13 @@ public IBinder onBind(Intent intent) {
413492 @ Override
414493 public void onSurfaceTextureAvailable (SurfaceTexture surface , int width , int height ) {
415494 textureSurface = new Surface (surface );
495+ applyPreviewTransform ();
416496 startPreview ();
417497 }
418498
419499 @ Override
420500 public void onSurfaceTextureSizeChanged (SurfaceTexture surface , int width , int height ) {
421- // no-op
501+ applyPreviewTransform ();
422502 }
423503
424504 @ Override
@@ -440,6 +520,7 @@ private void startPreview() {
440520 if (textureSurface == null || !textureSurface .isValid ()) {
441521 return ;
442522 }
523+ applyPreviewTransform ();
443524 CameraProbe .stopPreview ();
444525 CameraProbe .startPreview (cameraIndex , textureSurface );
445526 }
0 commit comments