Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b380516f authored by Eino-Ville Talvala's avatar Eino-Ville Talvala Committed by Ady Abraham
Browse files

Let window manager know about active camera users, part 1

- Each time a new app starts or stops using cameras, inform the
  window manager from the camera service proxy
- If an app uses multiple cameras, only notify on the start of the
  first camera use, and at the end of the last camera use.
- Actual implementation of window manager internals is next;
  temporary logging is in place for testing.

Test: On Pixel 3, verify that temporary logging appears as expected
  when apps open the camera and close it; verify multi-camera case by
  using TestingCamera2.1 to open/close camera IDs 2 and 3, which can
  be operated concurrently on Pixel 3.
Bug: 130744843

Change-Id: Ie808507fa7f35591cb19fee032413d6fb7700c9d
parent c0201ca9
Loading
Loading
Loading
Loading
+44 −5
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.wm.WindowManagerInternal;

import java.util.ArrayList;
import java.util.Collection;
@@ -90,8 +91,10 @@ public class CameraServiceProxy extends SystemService

    private ICameraService mCameraServiceRaw;

    // Map of currently active camera IDs
    private final ArrayMap<String, CameraUsageEvent> mActiveCameraUsage = new ArrayMap<>();
    private final List<CameraUsageEvent> mCameraUsageHistory = new ArrayList<>();

    private final MetricsLogger mLogger = new MetricsLogger();
    private static final String NFC_NOTIFICATION_PROP = "ro.camera.notify_nfc";
    private static final String NFC_SERVICE_BINDER_NAME = "nfc";
@@ -415,6 +418,24 @@ public class CameraServiceProxy extends SystemService
                    }
                    break;
                case ICameraServiceProxy.CAMERA_STATE_ACTIVE:
                    // Check current active camera IDs to see if this package is already talking to
                    // some camera
                    boolean alreadyActivePackage = false;
                    for (int i = 0; i < mActiveCameraUsage.size(); i++) {
                        if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
                            alreadyActivePackage = true;
                            break;
                        }
                    }
                    // If not already active, notify window manager about this new package using a
                    // camera
                    if (!alreadyActivePackage) {
                        WindowManagerInternal wmi =
                                LocalServices.getService(WindowManagerInternal.class);
                        wmi.addNonHighRefreshRatePackage(clientName);
                    }

                    // Update activity events
                    CameraUsageEvent newEvent = new CameraUsageEvent(facing, clientName, apiLevel);
                    CameraUsageEvent oldEvent = mActiveCameraUsage.put(cameraId, newEvent);
                    if (oldEvent != null) {
@@ -426,13 +447,31 @@ public class CameraServiceProxy extends SystemService
                case ICameraServiceProxy.CAMERA_STATE_IDLE:
                case ICameraServiceProxy.CAMERA_STATE_CLOSED:
                    CameraUsageEvent doneEvent = mActiveCameraUsage.remove(cameraId);
                    if (doneEvent != null) {
                    if (doneEvent == null) break;

                    doneEvent.markCompleted();
                    mCameraUsageHistory.add(doneEvent);
                    if (mCameraUsageHistory.size() > MAX_USAGE_HISTORY) {
                        dumpUsageEvents();
                    }

                    // Check current active camera IDs to see if this package is still talking to
                    // some camera
                    boolean stillActivePackage = false;
                    for (int i = 0; i < mActiveCameraUsage.size(); i++) {
                        if (mActiveCameraUsage.valueAt(i).mClientName.equals(clientName)) {
                            stillActivePackage = true;
                            break;
                        }
                    }
                    // If not longer active, notify window manager about this package being done
                    // with camera
                    if (!stillActivePackage) {
                        WindowManagerInternal wmi =
                                LocalServices.getService(WindowManagerInternal.class);
                        wmi.removeNonHighRefreshRatePackage(clientName);
                    }

                    break;
            }
            boolean isEmpty = mActiveCameraUsage.isEmpty();
+14 −0
Original line number Diff line number Diff line
@@ -492,4 +492,18 @@ public abstract class WindowManagerInternal {
     * @return {@code true} if the display should show IME when an input field become focused on it.
     */
    public abstract boolean shouldShowIme(int displayId);

    /**
     * Tell window manager about a package that should not be running with high refresh rate
     * setting until removeNonHighRefreshRatePackage is called for the same package.
     *
     * This must not be called again for the same package.
     */
    public abstract void addNonHighRefreshRatePackage(@NonNull String packageName);

    /**
     * Tell window manager to stop constraining refresh rate for the given package.
     */
    public abstract void removeNonHighRefreshRatePackage(@NonNull String packageName);

}
+13 −0
Original line number Diff line number Diff line
@@ -7446,6 +7446,19 @@ public class WindowManagerService extends IWindowManager.Stub
                return WindowManagerService.this.shouldShowIme(displayId);
            }
        }

        @Override
        public void addNonHighRefreshRatePackage(@NonNull String packageName) {
            // TODO
            Slog.i(TAG, "addNonHighRefreshRatePackage: " + packageName);
        }

        @Override
        public void removeNonHighRefreshRatePackage(@NonNull String packageName) {
            // TODO
            Slog.i(TAG, "removeNonHighRefreshRatePackage: " + packageName);
        }

    }

    void registerAppFreezeListener(AppFreezeListener listener) {