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

Commit 7e0f9699 authored by Darryl Johnson's avatar Darryl Johnson Committed by Android (Google) Code Review
Browse files

Merge "Add logic to forward foldable device state to native cameraserver."

parents d6dcb08f 4526eddd
Loading
Loading
Loading
Loading
+126 −14
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.server.camera;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -39,6 +40,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
@@ -48,6 +50,8 @@ import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
import com.android.server.wm.WindowManagerInternal;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -79,10 +83,19 @@ public class CameraServiceProxy extends SystemService

    // Handler message codes
    private static final int MSG_SWITCH_USER = 1;
    private static final int MSG_NOTIFY_DEVICE_STATE = 2;

    private static final int RETRY_DELAY_TIME = 20; //ms
    private static final int RETRY_TIMES = 60;

    @IntDef(flag = true, prefix = { "DEVICE_STATE_" }, value = {
            ICameraService.DEVICE_STATE_BACK_COVERED,
            ICameraService.DEVICE_STATE_FRONT_COVERED,
            ICameraService.DEVICE_STATE_FOLDED
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface DeviceStateFlags {}

    // Maximum entries to keep in usage history before dumping out
    private static final int MAX_USAGE_HISTORY = 100;

@@ -94,6 +107,15 @@ public class CameraServiceProxy extends SystemService
    private final Object mLock = new Object();
    private Set<Integer> mEnabledCameraUsers;
    private int mLastUser;
    // The current set of device state flags. May be different from mLastReportedDeviceState if the
    // native camera service has not been notified of the change.
    @GuardedBy("mLock")
    @DeviceStateFlags
    private int mDeviceState;
    // The most recent device state flags reported to the native camera server.
    @GuardedBy("mLock")
    @DeviceStateFlags
    private int mLastReportedDeviceState;

    private ICameraService mCameraServiceRaw;

@@ -185,6 +207,7 @@ public class CameraServiceProxy extends SystemService
                return;
            }
            notifySwitchWithRetries(RETRY_TIMES);
            notifyDeviceStateWithRetries(RETRY_TIMES);
        }

        @Override
@@ -218,12 +241,55 @@ public class CameraServiceProxy extends SystemService
        mLogWriterService.allowCoreThreadTimeOut(true);
    }

    /**
     * Sets the device state bits set within {@code deviceStateFlags} leaving all other bits the
     * same.
     * <p>
     * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
     *
     * @param deviceStateFlags a bitmask of the device state bits that should be set.
     *
     * @see #clearDeviceStateFlags(int)
     */
    public void setDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
            mDeviceState |= deviceStateFlags;
            if (mDeviceState != mLastReportedDeviceState) {
                notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
            }
        }
    }

    /**
     * Clears the device state bits set within {@code deviceStateFlags} leaving all other bits the
     * same.
     * <p>
     * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
     *
     * @param deviceStateFlags a bitmask of the device state bits that should be cleared.
     *
     * @see #setDeviceStateFlags(int)
     */
    public void clearDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
        synchronized (mLock) {
            mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
            mDeviceState &= ~deviceStateFlags;
            if (mDeviceState != mLastReportedDeviceState) {
                notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
            }
        }
    }

    @Override
    public boolean handleMessage(Message msg) {
        switch(msg.what) {
            case MSG_SWITCH_USER: {
                notifySwitchWithRetries(msg.arg1);
            } break;
            case MSG_NOTIFY_DEVICE_STATE: {
                notifyDeviceStateWithRetries(msg.arg1);
            } break;
            default: {
                Slog.e(TAG, "CameraServiceProxy error, invalid message: " + msg.what);
            } break;
@@ -386,6 +452,25 @@ public class CameraServiceProxy extends SystemService
        }
    }

    @Nullable
    private ICameraService getCameraServiceRawLocked() {
        if (mCameraServiceRaw == null) {
            IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
            if (cameraServiceBinder == null) {
                return null;
            }
            try {
                cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
            } catch (RemoteException e) {
                Slog.w(TAG, "Could not link to death of native camera service");
                return null;
            }

            mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
        }
        return mCameraServiceRaw;
    }

    private void switchUserLocked(int userHandle) {
        Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
        mLastUser = userHandle;
@@ -431,29 +516,56 @@ public class CameraServiceProxy extends SystemService
    private boolean notifyCameraserverLocked(int eventType, Set<Integer> updatedUserHandles) {
        // Forward the user switch event to the native camera service running in the cameraserver
        // process.
        if (mCameraServiceRaw == null) {
            IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
            if (cameraServiceBinder == null) {
        ICameraService cameraService = getCameraServiceRawLocked();
        if (cameraService == null) {
            Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
                return false; // Camera service not active, cannot evict user clients.
            return false;
        }

        try {
                cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
            mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
        } catch (RemoteException e) {
                Slog.w(TAG, "Could not link to death of native camera service");
            Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e);
            // Not much we can do if camera service is dead.
            return false;
        }
        return true;
    }

            mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
    private void notifyDeviceStateWithRetries(int retries) {
        synchronized (mLock) {
            notifyDeviceStateWithRetriesLocked(retries);
        }
    }

    private void notifyDeviceStateWithRetriesLocked(int retries) {
        if (notifyDeviceStateChangeLocked(mDeviceState)) {
            return;
        }
        if (retries <= 0) {
            return;
        }
        Slog.i(TAG, "Could not notify camera service of device state change, retrying...");
        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_NOTIFY_DEVICE_STATE, retries - 1,
                0, null), RETRY_DELAY_TIME);
    }

    private boolean notifyDeviceStateChangeLocked(@DeviceStateFlags int deviceState) {
        // Forward the state to the native camera service running in the cameraserver process.
        ICameraService cameraService = getCameraServiceRawLocked();
        if (cameraService == null) {
            Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
            return false;
        }

        try {
            mCameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
            mCameraServiceRaw.notifyDeviceStateChange(deviceState);
        } catch (RemoteException e) {
            Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e);
            // Not much we can do if camera service is dead.
            return false;
        }
        mLastReportedDeviceState = deviceState;
        return true;
    }

+27 −4
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.server.policy;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.ICameraService;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -26,11 +28,13 @@ import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IDisplayFoldListener;

import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.camera.CameraServiceProxy;
import com.android.server.wm.WindowManagerInternal;

/**
@@ -38,11 +42,13 @@ import com.android.server.wm.WindowManagerInternal;
 * TODO(b/126160895): Move DisplayFoldController from PhoneWindowManager to DisplayPolicy.
 */
class DisplayFoldController {

    private static final String TAG = "DisplayFoldController";

    private final WindowManagerInternal mWindowManagerInternal;
    private final DisplayManagerInternal mDisplayManagerInternal;
    // Camera service proxy can be disabled through a config.
    @Nullable
    private final CameraServiceProxy mCameraServiceProxy;
    private final int mDisplayId;
    private final Handler mHandler;

@@ -58,10 +64,12 @@ class DisplayFoldController {
    private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger();

    DisplayFoldController(WindowManagerInternal windowManagerInternal,
            DisplayManagerInternal displayManagerInternal, int displayId, Rect foldedArea,
            DisplayManagerInternal displayManagerInternal,
            @Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea,
            Handler handler) {
        mWindowManagerInternal = windowManagerInternal;
        mDisplayManagerInternal = displayManagerInternal;
        mCameraServiceProxy = cameraServiceProxy;
        mDisplayId = displayId;
        mFoldedArea = new Rect(foldedArea);
        mHandler = handler;
@@ -116,6 +124,16 @@ class DisplayFoldController {
            }
        }

        if (mCameraServiceProxy != null) {
            if (folded) {
                mCameraServiceProxy.setDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
            } else {
                mCameraServiceProxy.clearDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
            }
        } else {
            Slog.w(TAG, "Camera service unavailable to toggle folded state.");
        }

        mDurationLogger.setDeviceFolded(folded);
        mDurationLogger.logFocusedAppWithFoldState(folded, mFocusedApp);
        mFolded = folded;
@@ -193,8 +211,13 @@ class DisplayFoldController {
    }

    static DisplayFoldController create(Context context, int displayId) {
        final WindowManagerInternal windowManagerService =
                LocalServices.getService(WindowManagerInternal.class);
        final DisplayManagerInternal displayService =
                LocalServices.getService(DisplayManagerInternal.class);
        final CameraServiceProxy cameraServiceProxy =
                LocalServices.getService(CameraServiceProxy.class);

        final String configFoldedArea = context.getResources().getString(
                com.android.internal.R.string.config_foldedArea);
        final Rect foldedArea;
@@ -204,7 +227,7 @@ class DisplayFoldController {
            foldedArea = Rect.unflattenFromString(configFoldedArea);
        }

        return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class),
                displayService, displayId, foldedArea, DisplayThread.getHandler());
        return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy,
                displayId, foldedArea, DisplayThread.getHandler());
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -1266,6 +1266,12 @@ public final class SystemServer implements Dumpable {
            inputManager = new InputManagerService(context);
            t.traceEnd();

            if (!disableCameraService) {
                t.traceBegin("StartCameraServiceProxy");
                mSystemServiceManager.startService(CameraServiceProxy.class);
                t.traceEnd();
            }

            t.traceBegin("StartWindowManagerService");
            // WMS needs sensor service ready
            ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
@@ -2200,12 +2206,6 @@ public final class SystemServer implements Dumpable {
            t.traceEnd();
        }

        if (!disableCameraService) {
            t.traceBegin("StartCameraServiceProxy");
            mSystemServiceManager.startService(CameraServiceProxy.class);
            t.traceEnd();
        }

        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
            t.traceBegin("StartIoTSystemService");
            mSystemServiceManager.startService(IOT_SERVICE_CLASS);