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

Commit 305cec67 authored by Eino-Ville Talvala's avatar Eino-Ville Talvala
Browse files

Camera muting via sensor test pattern

Currently enabled/disabled via
  adb shell cmd media.camera set-camera-mute <1/0>

TODO:
- Connect to the wider sensor muting feature

This is suitable for testing apps to see how they react, and how Pixel phones
implement test patterns.

Test: GoogleCameraApp and AOSP Camera2 on sunfish appear to act as if they were in a dark room,
      no crashes, after calling 'adb shell cmd media.camera set-camera-mute 1'
Bug: 170156750
Change-Id: I85e1d2d6ee7d9bf1aee99c4bc8d5f98d36754228
parent 40e3a7a2
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -1686,6 +1686,11 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8&
            client->setRotateAndCropOverride(mOverrideRotateAndCropMode);
        }

        // Set camera muting behavior
        if (client->supportsCameraMute()) {
            client->setCameraMute(mOverrideCameraMuteMode);
        }

        if (shimUpdateOnly) {
            // If only updating legacy shim parameters, immediately disconnect client
            mServiceLock.unlock();
@@ -3887,6 +3892,8 @@ status_t CameraService::shellCommand(int in, int out, int err, const Vector<Stri
        return handleSetImageDumpMask(args);
    } else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
        return handleGetImageDumpMask(out);
    } else if (args.size() >= 2 && args[0] == String16("set-camera-mute")) {
        return handleSetCameraMute(args);
    } else if (args.size() == 1 && args[0] == String16("help")) {
        printHelp(out);
        return NO_ERROR;
@@ -4009,6 +4016,29 @@ status_t CameraService::handleGetImageDumpMask(int out) {
    return dprintf(out, "Image dump mask: %d\n", mImageDumpMask);
}

status_t CameraService::handleSetCameraMute(const Vector<String16>& args) {
    int muteValue = strtol(String8(args[1]), nullptr, 10);
    if (errno != 0) return BAD_VALUE;

    if (muteValue < 0 || muteValue > 1) return BAD_VALUE;
    Mutex::Autolock lock(mServiceLock);

    mOverrideCameraMuteMode = (muteValue == 1);

    const auto clients = mActiveClientManager.getAll();
    for (auto& current : clients) {
        if (current != nullptr) {
            const auto basicClient = current->getValue();
            if (basicClient.get() != nullptr) {
                if (basicClient->supportsCameraMute()) {
                    basicClient->setCameraMute(mOverrideCameraMuteMode);
                }
            }
        }
    }

    return OK;
}

status_t CameraService::printHelp(int out) {
    return dprintf(out, "Camera service commands:\n"
@@ -4021,6 +4051,7 @@ status_t CameraService::printHelp(int out) {
        "  set-image-dump-mask <MASK> specifies the formats to be saved to disk\n"
        "      Valid values 0=OFF, 1=ON for JPEG\n"
        "  get-image-dump-mask returns the current image-dump-mask value\n"
        "  set-camera-mute <0/1> enable or disable camera muting\n"
        "  help print this message\n");
}

+12 −0
Original line number Diff line number Diff line
@@ -278,6 +278,12 @@ public:
        // Override rotate-and-crop AUTO behavior
        virtual status_t setRotateAndCropOverride(uint8_t rotateAndCrop) = 0;

        // Whether the client supports camera muting (black only output)
        virtual bool supportsCameraMute() = 0;

        // Set/reset camera mute
        virtual status_t setCameraMute(bool enabled) = 0;

    protected:
        BasicClient(const sp<CameraService>& cameraService,
                const sp<IBinder>& remoteCallback,
@@ -1044,6 +1050,9 @@ private:
    // Get the mask for image dump to disk
    status_t handleGetImageDumpMask(int out);

    // Set the camera mute state
    status_t handleSetCameraMute(const Vector<String16>& args);

    // Prints the shell command help
    status_t printHelp(int out);

@@ -1088,6 +1097,9 @@ private:

    // Current image dump mask
    uint8_t mImageDumpMask = 0;

    // Current camera mute mode
    bool mOverrideCameraMuteMode = false;
};

} // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -2296,6 +2296,14 @@ status_t Camera2Client::setRotateAndCropOverride(uint8_t rotateAndCrop) {
        static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
}

bool Camera2Client::supportsCameraMute() {
    return mDevice->supportsCameraMute();
}

status_t Camera2Client::setCameraMute(bool enabled) {
    return mDevice->setCameraMute(enabled);
}

status_t Camera2Client::waitUntilCurrentRequestIdLocked() {
    int32_t activeRequestId = mStreamingProcessor->getActiveRequestId();
    if (activeRequestId != 0) {
+3 −0
Original line number Diff line number Diff line
@@ -87,6 +87,9 @@ public:
    virtual int32_t         getGlobalAudioRestriction();
    virtual status_t        setRotateAndCropOverride(uint8_t rotateAndCrop);

    virtual bool            supportsCameraMute();
    virtual status_t        setCameraMute(bool enabled);

    /**
     * Interface used by CameraService
     */
+8 −0
Original line number Diff line number Diff line
@@ -1532,6 +1532,14 @@ status_t CameraDeviceClient::setRotateAndCropOverride(uint8_t rotateAndCrop) {
        static_cast<camera_metadata_enum_android_scaler_rotate_and_crop_t>(rotateAndCrop));
}

bool CameraDeviceClient::supportsCameraMute() {
    return mDevice->supportsCameraMute();
}

status_t CameraDeviceClient::setCameraMute(bool enabled) {
    return mDevice->setCameraMute(enabled);
}

binder::Status CameraDeviceClient::switchToOffline(
        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
        const std::vector<int>& offlineOutputIds,
Loading