Merge "Camera: Use original format and dataSpace for reconfigure" into qt-dev
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.cpp b/media/codec2/components/opus/C2SoftOpusEnc.cpp
index 384d58b..70d1965 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.cpp
+++ b/media/codec2/components/opus/C2SoftOpusEnc.cpp
@@ -471,11 +471,11 @@
         uint8_t* outPtr = wView.data() + mBytesEncoded;
         int encodedBytes =
             opus_multistream_encode(mEncoder, mInputBufferPcm16,
-                                    mNumSamplesPerFrame, outPtr, kMaxPayload);
+                                    mNumSamplesPerFrame, outPtr, kMaxPayload - mBytesEncoded);
         ALOGV("encoded %i Opus bytes from %zu PCM bytes", encodedBytes,
               processSize);
 
-        if (encodedBytes < 0 || encodedBytes > kMaxPayload) {
+        if (encodedBytes < 0 || encodedBytes > (kMaxPayload - mBytesEncoded)) {
             ALOGE("opus_encode failed, encodedBytes : %d", encodedBytes);
             mSignalledError = true;
             work->result = C2_CORRUPTED;
diff --git a/media/codec2/components/opus/C2SoftOpusEnc.h b/media/codec2/components/opus/C2SoftOpusEnc.h
index 69e5240..2b4d8f2 100644
--- a/media/codec2/components/opus/C2SoftOpusEnc.h
+++ b/media/codec2/components/opus/C2SoftOpusEnc.h
@@ -47,7 +47,9 @@
 private:
     /* OPUS_FRAMESIZE_20_MS */
     const int kFrameSize = 960;
-    const int kMaxPayload = 4000;
+    const int kMaxSampleRate = 48000;
+    const int kMinSampleRate = 8000;
+    const int kMaxPayload = (4000 * kMaxSampleRate) / kMinSampleRate;
     const int kMaxNumChannels = 8;
 
     std::shared_ptr<IntfImpl> mIntf;
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index c20ca73..702ad6f 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -201,9 +201,10 @@
      * \param colorFormat desired SDK color format for the MediaImage (if this is a flexible format,
      *        an attempt is made to simply represent the graphic view as a flexible SDK format
      *        without a memcpy)
+     * \param copy whether the converter is used for copy or not
      */
     GraphicView2MediaImageConverter(
-            const C2GraphicView &view, int32_t colorFormat)
+            const C2GraphicView &view, int32_t colorFormat, bool copy)
         : mInitCheck(NO_INIT),
           mView(view),
           mWidth(view.width()),
@@ -255,41 +256,44 @@
                 }
                 switch (mColorFormat) {
                     case COLOR_FormatYUV420Flexible:
-                    {  // try to map directly. check if the planes are near one another
-                        const uint8_t *minPtr = mView.data()[0];
-                        const uint8_t *maxPtr = mView.data()[0];
-                        int32_t planeSize = 0;
-                        for (uint32_t i = 0; i < layout.numPlanes; ++i) {
-                            const C2PlaneInfo &plane = layout.planes[i];
-                            ssize_t minOffset = plane.minOffset(mWidth, mHeight);
-                            ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
-                            if (minPtr > mView.data()[i] + minOffset) {
-                                minPtr = mView.data()[i] + minOffset;
-                            }
-                            if (maxPtr < mView.data()[i] + maxOffset) {
-                                maxPtr = mView.data()[i] + maxOffset;
-                            }
-                            planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
-                                    / plane.rowSampling / plane.colSampling * divUp(mAllocatedDepth, 8u);
-                        }
-
-                        if ((maxPtr - minPtr + 1) <= planeSize) {
-                            // FIXME: this is risky as reading/writing data out of bound results in
-                            //        an undefined behavior, but gralloc does assume a contiguous
-                            //        mapping
+                        if (!copy) {
+                            // try to map directly. check if the planes are near one another
+                            const uint8_t *minPtr = mView.data()[0];
+                            const uint8_t *maxPtr = mView.data()[0];
+                            int32_t planeSize = 0;
                             for (uint32_t i = 0; i < layout.numPlanes; ++i) {
                                 const C2PlaneInfo &plane = layout.planes[i];
-                                mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
-                                mediaImage->mPlane[i].mColInc = plane.colInc;
-                                mediaImage->mPlane[i].mRowInc = plane.rowInc;
-                                mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
-                                mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+                                ssize_t minOffset = plane.minOffset(mWidth, mHeight);
+                                ssize_t maxOffset = plane.maxOffset(mWidth, mHeight);
+                                if (minPtr > mView.data()[i] + minOffset) {
+                                    minPtr = mView.data()[i] + minOffset;
+                                }
+                                if (maxPtr < mView.data()[i] + maxOffset) {
+                                    maxPtr = mView.data()[i] + maxOffset;
+                                }
+                                planeSize += std::abs(plane.rowInc) * align(mHeight, 64)
+                                        / plane.rowSampling / plane.colSampling
+                                        * divUp(mAllocatedDepth, 8u);
                             }
-                            mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr + 1);
-                            break;
+
+                            if ((maxPtr - minPtr + 1) <= planeSize) {
+                                // FIXME: this is risky as reading/writing data out of bound results
+                                //        in an undefined behavior, but gralloc does assume a
+                                //        contiguous mapping
+                                for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+                                    const C2PlaneInfo &plane = layout.planes[i];
+                                    mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
+                                    mediaImage->mPlane[i].mColInc = plane.colInc;
+                                    mediaImage->mPlane[i].mRowInc = plane.rowInc;
+                                    mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
+                                    mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+                                }
+                                mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
+                                                       maxPtr - minPtr + 1);
+                                break;
+                            }
                         }
-                    }
-                    [[fallthrough]];
+                        [[fallthrough]];
 
                     case COLOR_FormatYUV420Planar:
                     case COLOR_FormatYUV420PackedPlanar:
@@ -503,7 +507,7 @@
     int32_t colorFormat = COLOR_FormatYUV420Flexible;
     (void)format->findInt32("color-format", &colorFormat);
 
-    GraphicView2MediaImageConverter converter(view, colorFormat);
+    GraphicView2MediaImageConverter converter(view, colorFormat, false /* copy */);
     if (converter.initCheck() != OK) {
         ALOGD("Converter init failed: %d", converter.initCheck());
         return nullptr;
@@ -615,7 +619,7 @@
     int32_t colorFormat = COLOR_FormatYUV420Flexible;
     (void)format->findInt32("color-format", &colorFormat);
 
-    GraphicView2MediaImageConverter converter(*view, colorFormat);
+    GraphicView2MediaImageConverter converter(*view, colorFormat, false /* copy */);
     if (converter.initCheck() != OK) {
         ALOGD("Converter init failed: %d", converter.initCheck());
         return nullptr;
@@ -708,7 +712,7 @@
     const_cast<ConstGraphicBlockBuffer *>(this)->format()->findInt32("color-format", &colorFormat);
 
     GraphicView2MediaImageConverter converter(
-            buffer->data().graphicBlocks()[0].map().get(), colorFormat);
+            buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
     if (converter.initCheck() != OK) {
         ALOGD("ConstGraphicBlockBuffer::canCopy: converter init failed: %d", converter.initCheck());
         return false;
@@ -730,7 +734,7 @@
     format()->findInt32("color-format", &colorFormat);
 
     GraphicView2MediaImageConverter converter(
-            buffer->data().graphicBlocks()[0].map().get(), colorFormat);
+            buffer->data().graphicBlocks()[0].map().get(), colorFormat, true /* copy */);
     if (converter.initCheck() != OK) {
         ALOGD("ConstGraphicBlockBuffer::copy: converter init failed: %d", converter.initCheck());
         return false;
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 1e884ef..bf2a07e 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -137,14 +137,14 @@
         int32_t dst_stride_v = img->mPlane[2].mRowInc;
         if (IsNV12(view) && IsI420(img)) {
             if (!libyuv::NV12ToI420(src_y, src_stride_y, src_u, src_stride_u, dst_y, dst_stride_y,
-                                    dst_u, dst_stride_u, dst_v, dst_stride_v, view.width(),
-                                    view.height())) {
+                                    dst_u, dst_stride_u, dst_v, dst_stride_v, view.crop().width,
+                                    view.crop().height)) {
                 return OK;
             }
         } else {
             if (!libyuv::I420ToNV12(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
-                                    dst_y, dst_stride_y, dst_u, dst_stride_u, view.width(),
-                                    view.height())) {
+                                    dst_y, dst_stride_y, dst_u, dst_stride_u, view.crop().width,
+                                    view.crop().height)) {
                 return OK;
             }
         }
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index b1eb301..23022e4 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -2109,8 +2109,10 @@
 
                 if (!strcmp("A_AAC", codecID)) {
                     AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
-                    CHECK(codecPrivateSize >= 2);
-
+                    if (codecPrivateSize < 2) {
+                        ALOGW("Incomplete AAC Codec Info %zu byte", codecPrivateSize);
+                        continue;
+                    }
                     addESDSFromCodecPrivate(
                             meta, true, codecPrivate, codecPrivateSize);
                 } else if (!strcmp("A_VORBIS", codecID)) {
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 527bb77..9d5890c 100755
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -1197,45 +1197,16 @@
                         AMEDIAFORMAT_KEY_SAMPLE_RATE, sample_rate);
             }
 
-            // If format type is 'alac', it is necessary to get the parameters
-            // from a alac atom spreading behind the frma atom.
-            // See 'external/alac/ALACMagicCookieDescription.txt'.
-            if (original_fourcc == FOURCC("alac")) {
-                // Store ALAC magic cookie (decoder needs it).
-                uint8_t alacInfo[12];
-                data_offset = *offset;
-                if (mDataSource->readAt(
-                        data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
-                    return ERROR_IO;
+            if (!mIsQT && original_fourcc == FOURCC("alac")) {
+                off64_t tmpOffset = *offset;
+                status_t err = parseALACSampleEntry(&tmpOffset);
+                if (err != OK) {
+                    ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                    return err;
                 }
-                uint32_t size = U32_AT(&alacInfo[0]);
-                if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
-                        (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
-                        (U32_AT(&alacInfo[8]) != 0)) {
-                    return ERROR_MALFORMED;
-                }
-
-                data_offset += sizeof(alacInfo);
-                uint8_t cookie[size - sizeof(alacInfo)];
-                if (mDataSource->readAt(
-                        data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
-                    return ERROR_IO;
-                }
-
-                uint8_t bitsPerSample = cookie[5];
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
-                AMediaFormat_setBuffer(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
-
-                // Add the size of ALAC Specific Info (36 bytes) and terminator
-                // atom (8 bytes).
-                *offset += (size + 8);
+                *offset = tmpOffset + 8;
             }
+
             break;
         }
 
@@ -1653,7 +1624,18 @@
         case 0x6D730055: // "ms U" mp3 audio
         {
             if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
+
+                if (chunk_type == FOURCC("alac")) {
+                    off64_t offsetTmp = *offset;
+                    status_t err = parseALACSampleEntry(&offsetTmp);
+                    if (err != OK) {
+                        ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                        return err;
+                    }
+                }
+
                 // Ignore all atoms embedded in QT wave atom
+                ALOGV("Ignore all atoms embedded in QT wave atom");
                 *offset += chunk_size;
                 break;
             }
@@ -1792,39 +1774,14 @@
                 CHECK_EQ(*offset, stop_offset);
             }
 
-            if (chunk_type == FOURCC("alac")) {
-
-                // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
-                // Store ALAC magic cookie (decoder needs it).
-                uint8_t alacInfo[12];
+            if (!mIsQT && chunk_type == FOURCC("alac")) {
                 data_offset += sizeof(buffer);
-                if (mDataSource->readAt(
-                        data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
-                    return ERROR_IO;
-                }
-                uint32_t size = U32_AT(&alacInfo[0]);
-                if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
-                        (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
-                        (U32_AT(&alacInfo[8]) != 0)) {
-                    return ERROR_MALFORMED;
-                }
-                data_offset += sizeof(alacInfo);
-                uint8_t cookie[size - sizeof(alacInfo)];
-                if (mDataSource->readAt(
-                        data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
-                    return ERROR_IO;
-                }
 
-                uint8_t bitsPerSample = cookie[5];
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
-                AMediaFormat_setInt32(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
-                AMediaFormat_setBuffer(mLastTrack->meta,
-                        AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
-                data_offset += sizeof(cookie);
+                status_t err = parseALACSampleEntry(&data_offset);
+                if (err != OK) {
+                    ALOGE("parseALACSampleEntry err:%d Line:%d", err, __LINE__);
+                    return err;
+                }
                 *offset = data_offset;
                 CHECK_EQ(*offset, stop_offset);
             }
@@ -3289,6 +3246,45 @@
     return OK;
 }
 
+status_t MPEG4Extractor::parseALACSampleEntry(off64_t *offset) {
+    // See 'external/alac/ALACMagicCookieDescription.txt for the detail'.
+    // Store ALAC magic cookie (decoder needs it).
+    uint8_t alacInfo[12];
+    off64_t data_offset = *offset;
+
+    if (mDataSource->readAt(
+            data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) {
+        return ERROR_IO;
+    }
+    uint32_t size = U32_AT(&alacInfo[0]);
+    if ((size != ALAC_SPECIFIC_INFO_SIZE) ||
+            (U32_AT(&alacInfo[4]) != FOURCC("alac")) ||
+            (U32_AT(&alacInfo[8]) != 0)) {
+        ALOGV("Size:%u, U32_AT(&alacInfo[4]):%u, U32_AT(&alacInfo[8]):%u",
+            size, U32_AT(&alacInfo[4]), U32_AT(&alacInfo[8]));
+        return ERROR_MALFORMED;
+    }
+    data_offset += sizeof(alacInfo);
+    uint8_t cookie[size - sizeof(alacInfo)];
+    if (mDataSource->readAt(
+            data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) {
+        return ERROR_IO;
+    }
+
+    uint8_t bitsPerSample = cookie[5];
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, bitsPerSample);
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_CHANNEL_COUNT, cookie[9]);
+    AMediaFormat_setInt32(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_SAMPLE_RATE, U32_AT(&cookie[20]));
+    AMediaFormat_setBuffer(mLastTrack->meta,
+            AMEDIAFORMAT_KEY_CSD_0, cookie, sizeof(cookie));
+    data_offset += sizeof(cookie);
+    *offset = data_offset;
+    return OK;
+}
+
 status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
   ALOGV("MPEG4Extractor::parseSegmentIndex");
 
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index e10bf8a..fcddbb8 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -179,6 +179,7 @@
     status_t parseAC3SpecificBox(off64_t offset);
     status_t parseEAC3SpecificBox(off64_t offset);
     status_t parseAC4SpecificBox(off64_t offset);
+    status_t parseALACSampleEntry(off64_t *offset);
     void adjustRawDefaultFrameSize();
 
     MPEG4Extractor(const MPEG4Extractor &);
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 59265fe..c7e92cd 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -157,6 +157,12 @@
                  buffer->size() + bufferRemaining);
 
             sp<ABuffer> copy = new ABuffer(buffer->size() + bufferRemaining);
+            if (copy->data() == NULL) {
+                android_errorWriteLog(0x534e4554, "68399439");
+                ALOGE("not enough memory to download: requesting %zu + %zu",
+                        buffer->size(), bufferRemaining);
+                return NO_MEMORY;
+            }
             memcpy(copy->data(), buffer->data(), buffer->size());
             copy->setRange(0, buffer->size());
 
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 7ec0e4c..1c1f5e6 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -70,6 +70,7 @@
     ],
 
     shared_libs: [
+        "libbase",
         "libdl",
         "libexif",
         "libui",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a87ebdf..3e62102 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -33,6 +33,7 @@
 
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
 #include <binder/ActivityManager.h>
 #include <binder/AppOpsManager.h>
 #include <binder/IPCThreadState.h>
@@ -81,6 +82,7 @@
 
 namespace android {
 
+using base::StringPrintf;
 using binder::Status;
 using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
 using hardware::ICamera;
@@ -2366,6 +2368,13 @@
         }
         mClientPackageName = packages[0];
     }
+    if (hardware::IPCThreadState::self()->isServingCall()) {
+        std::string vendorClient =
+                StringPrintf("vendor.client.pid<%d>", CameraThreadState::getCallingPid());
+        mClientPackageName = String16(vendorClient.c_str());
+    } else {
+        mAppOpsManager = std::make_unique<AppOpsManager>();
+    }
 }
 
 CameraService::BasicClient::~BasicClient() {
@@ -2381,8 +2390,7 @@
     mDisconnected = true;
 
     sCameraService->removeByClient(this);
-    sCameraService->logDisconnected(mCameraIdStr, mClientPid,
-            String8(mClientPackageName));
+    sCameraService->logDisconnected(mCameraIdStr, mClientPid, String8(mClientPackageName));
     sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
             mCameraIdStr.c_str());
 
@@ -2432,31 +2440,31 @@
 status_t CameraService::BasicClient::startCameraOps() {
     ATRACE_CALL();
 
-    int32_t res;
-    // Notify app ops that the camera is not available
-    mOpsCallback = new OpsCallback(this);
-
     {
         ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
               __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
     }
+    if (mAppOpsManager != nullptr) {
+        // Notify app ops that the camera is not available
+        mOpsCallback = new OpsCallback(this);
+        int32_t res;
+        mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
+                mClientPackageName, mOpsCallback);
+        res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
+                mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
 
-    mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
-            mClientPackageName, mOpsCallback);
-    res = mAppOpsManager.startOpNoThrow(AppOpsManager::OP_CAMERA,
-            mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+        if (res == AppOpsManager::MODE_ERRORED) {
+            ALOGI("Camera %s: Access for \"%s\" has been revoked",
+                    mCameraIdStr.string(), String8(mClientPackageName).string());
+            return PERMISSION_DENIED;
+        }
 
-    if (res == AppOpsManager::MODE_ERRORED) {
-        ALOGI("Camera %s: Access for \"%s\" has been revoked",
-                mCameraIdStr.string(), String8(mClientPackageName).string());
-        return PERMISSION_DENIED;
-    }
-
-    if (res == AppOpsManager::MODE_IGNORED) {
-        ALOGI("Camera %s: Access for \"%s\" has been restricted",
-                mCameraIdStr.string(), String8(mClientPackageName).string());
-        // Return the same error as for device policy manager rejection
-        return -EACCES;
+        if (res == AppOpsManager::MODE_IGNORED) {
+            ALOGI("Camera %s: Access for \"%s\" has been restricted",
+                    mCameraIdStr.string(), String8(mClientPackageName).string());
+            // Return the same error as for device policy manager rejection
+            return -EACCES;
+        }
     }
 
     mOpsActive = true;
@@ -2483,10 +2491,11 @@
     // Check if startCameraOps succeeded, and if so, finish the camera op
     if (mOpsActive) {
         // Notify app ops that the camera is available again
-        mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
-                mClientPackageName);
-        mOpsActive = false;
-
+        if (mAppOpsManager != nullptr) {
+            mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
+                    mClientPackageName);
+            mOpsActive = false;
+        }
         // This function is called when a client disconnects. This should
         // release the camera, but actually only if it was in a proper
         // functional state, i.e. with status NOT_AVAILABLE
@@ -2506,8 +2515,8 @@
                 mCameraIdStr, mCameraFacing, mClientPackageName, apiLevel);
     }
     // Always stop watching, even if no camera op is active
-    if (mOpsCallback != NULL) {
-        mAppOpsManager.stopWatchingMode(mOpsCallback);
+    if (mOpsCallback != nullptr && mAppOpsManager != nullptr) {
+        mAppOpsManager->stopWatchingMode(mOpsCallback);
     }
     mOpsCallback.clear();
 
@@ -2516,19 +2525,18 @@
     return OK;
 }
 
-void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
+void CameraService::BasicClient::opChanged(int32_t op, const String16&) {
     ATRACE_CALL();
-
-    String8 name(packageName);
-    String8 myName(mClientPackageName);
-
+    if (mAppOpsManager == nullptr) {
+        return;
+    }
     if (op != AppOpsManager::OP_CAMERA) {
         ALOGW("Unexpected app ops notification received: %d", op);
         return;
     }
 
     int32_t res;
-    res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
+    res = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA,
             mClientUid, mClientPackageName);
     ALOGV("checkOp returns: %d, %s ", res,
             res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
@@ -2538,7 +2546,7 @@
 
     if (res != AppOpsManager::MODE_ALLOWED) {
         ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.string(),
-                myName.string());
+              String8(mClientPackageName).string());
         block();
     }
 }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index b8cec2c..065157d 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -293,7 +293,7 @@
         status_t                        finishCameraOps();
 
     private:
-        AppOpsManager                   mAppOpsManager;
+        std::unique_ptr<AppOpsManager>  mAppOpsManager = nullptr;
 
         class OpsCallback : public BnAppOpsCallback {
         public: