diff options
36 files changed, 941 insertions, 129 deletions
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h index 0d943b7800..6e5da52cb5 100644 --- a/include/android/imagedecoder.h +++ b/include/android/imagedecoder.h @@ -15,12 +15,24 @@   */  /** - * @addtogroup ImageDecoder + * @defgroup ImageDecoder + * + * Functions for converting encoded images into RGBA pixels. + * + * Similar to the Java counterpart android.graphics.ImageDecoder, it can be used + * to decode images like PNG, JPEG, GIF, WEBP and HEIF. It has similar options + * for scaling, cropping, and choosing the output format. Unlike the Java API, + * which can create an android.graphics.Bitmap or + * android.graphics.drawable.Drawable object, AImageDecoder decodes directly + * into memory provided by the client. For more information, see the + * <a href="https://developer.android.com/ndk/guides/image-decoder">Image decoder</a> + * developer guide.   * @{   */  /** - * @file imageDecoder.h + * @file imagedecoder.h + * @brief API for decoding images.   */  #ifndef ANDROID_IMAGE_DECODER_H @@ -38,32 +50,54 @@ struct AAsset;  #if __ANDROID_API__ >= 30 -/** AImageDecoder functions result code. */ +/** + *  {@link AImageDecoder} functions result code. Many functions will return one of these + *  to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason + *  for the failure. On failure, any out-parameters should be considered + *  uninitialized, except where specified. + */  enum { -    // Decoding was successful and complete. +    /** +     * Decoding was successful and complete. +     */      ANDROID_IMAGE_DECODER_SUCCESS = 0, -    // The input was incomplete. In decodeImage, this means a partial -    // image was decoded. Undecoded lines are all zeroes. -    // In AImageDecoder_create*, no AImageDecoder was created. +    /** +     * The input was incomplete. +     */      ANDROID_IMAGE_DECODER_INCOMPLETE = -1, -    // The input contained an error after decoding some lines. Similar to -    // INCOMPLETE, above. +    /** +     * The input contained an error after decoding some lines. +     */      ANDROID_IMAGE_DECODER_ERROR = -2, -    // Could not convert, e.g. attempting to decode an image with -    // alpha to an opaque format. +    /** +     * Could not convert. For example, attempting to decode an image with +     * alpha to an opaque format. +     */      ANDROID_IMAGE_DECODER_INVALID_CONVERSION = -3, -    // The scale is invalid. It may have overflowed, or it may be incompatible -    // with the current alpha setting. +    /** +     * The scale is invalid. It may have overflowed, or it may be incompatible +     * with the current alpha setting. +     */      ANDROID_IMAGE_DECODER_INVALID_SCALE = -4, -    // Some other parameter was bad (e.g. pixels) +    /** +     * Some other parameter was bad. +     */      ANDROID_IMAGE_DECODER_BAD_PARAMETER = -5, -    // Input was invalid i.e. broken before decoding any pixels. +    /** +     * Input was invalid before decoding any pixels. +     */      ANDROID_IMAGE_DECODER_INVALID_INPUT = -6, -    // A seek was required, and failed. +    /** +     * A seek was required and it failed. +     */      ANDROID_IMAGE_DECODER_SEEK_ERROR = -7, -    // Some other error (e.g. OOM) +    /** +     * Some other error. For example, an internal allocation failed. +     */      ANDROID_IMAGE_DECODER_INTERNAL_ERROR = -8, -    // We did not recognize the format +    /** +     * AImageDecoder did not recognize the format. +     */      ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9  }; @@ -76,36 +110,45 @@ struct AImageDecoder;   * - {@link AImageDecoder_createFromAAsset}   * - {@link AImageDecoder_createFromFd}   * - {@link AImageDecoder_createFromBuffer} + * + * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve + * information about the encoded image. Other functions, like + * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and + * {@link AImageDecoder_decode} will decode into client provided memory. + * + * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across + * threads.   */  typedef struct AImageDecoder AImageDecoder;  /** - * Create a new AImageDecoder from an AAsset. + * Create a new {@link AImageDecoder} from an {@link AAsset}.   *   * @param asset {@link AAsset} containing encoded image data. Client is still - *              responsible for calling {@link AAsset_close} on it. + *              responsible for calling {@link AAsset_close} on it, which may be + *              done after deleting the returned {@link AImageDecoder}.   * @param outDecoder On success (i.e. return value is   *                   {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to   *                   a newly created {@link AImageDecoder}. Caller is   *                   responsible for calling {@link AImageDecoder_delete} on it.   * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value - *         indicating reason for the failure. + *         indicating the reason for the failure.   */  int AImageDecoder_createFromAAsset(struct AAsset* asset, AImageDecoder** outDecoder)          __INTRODUCED_IN(30);  /** - * Create a new AImageDecoder from a file descriptor. + * Create a new {@link AImageDecoder} from a file descriptor.   *   * @param fd Seekable, readable, open file descriptor for encoded data.   *           Client is still responsible for closing it, which may be done - *           *after* deleting the returned AImageDecoder. + *           after deleting the returned {@link AImageDecoder}.   * @param outDecoder On success (i.e. return value is   *                   {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to   *                   a newly created {@link AImageDecoder}. Caller is   *                   responsible for calling {@link AImageDecoder_delete} on it.   * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value - *         indicating reason for the failure. + *         indicating the reason for the failure.   */  int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) __INTRODUCED_IN(30); @@ -113,7 +156,7 @@ int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) __INTRODUCED_   * Create a new AImageDecoder from a buffer.   *   * @param buffer Pointer to encoded data. Must be valid for the entire time - *               the AImageDecoder is used. + *               the {@link AImageDecoder} is used.   * @param length Byte length of buffer.   * @param outDecoder On success (i.e. return value is   *                   {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to @@ -136,7 +179,7 @@ void AImageDecoder_delete(AImageDecoder* decoder) __INTRODUCED_IN(30);   * @param format {@link AndroidBitmapFormat} to use for the output.   * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} if the format is compatible   *         with the image and {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION} - *         otherwise. In the latter case, the AImageDecoder uses the + *         otherwise. In the latter case, the {@link AImageDecoder} uses the   *         format it was already planning to use (either its default   *         or a previously successful setting from this function).   */ @@ -146,23 +189,25 @@ int AImageDecoder_setAndroidBitmapFormat(AImageDecoder*,  /**   * Specify whether the output's pixels should be unpremultiplied.   * - * By default, the decoder will premultiply the pixels, if they have alpha. Pass - * false to this method to leave them unpremultiplied. This has no effect on an + * By default, {@link AImageDecoder_decodeImage} will premultiply the pixels, if they have alpha. + * Pass true to this method to leave them unpremultiplied. This has no effect on an   * opaque image.   * - * @param required Pass true to leave the pixels unpremultiplied. - * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success + * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied. + * @return an enum describing whether the call succeeded. + *         - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success   *         - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION} if the conversion   *           is not possible   *         - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for bad parameters   */ -int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*, bool required) __INTRODUCED_IN(30); +int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*, +                                             bool unpremultipliedRequired) __INTRODUCED_IN(30);  /**   * Choose the dataspace for the output.   * - * Not supported for {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support - * an ADataSpace. + * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support + * an {@link ADataSpace}.   *   * @param dataspace The {@link ADataSpace} to decode into. An ADataSpace   *                  specifies how to interpret the colors. By default, @@ -170,10 +215,10 @@ int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*, bool required) __IN   *                  {@link AImageDecoderHeaderInfo_getDataSpace}. If this   *                  parameter is set to a different ADataSpace, AImageDecoder   *                  will transform the output into the specified ADataSpace. - * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success - *         - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for a null - *           AImageDecoder or an integer that does not correspond to an - *           ADataSpace value. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or + *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for a null + *         {@link AImageDecoder} or an integer that does not correspond to an + *         {@link ADataSpace} value.   */  int AImageDecoder_setDataSpace(AImageDecoder*, int32_t dataspace) __INTRODUCED_IN(30); @@ -191,10 +236,11 @@ int AImageDecoder_setDataSpace(AImageDecoder*, int32_t dataspace) __INTRODUCED_I   *              {@link AImageDecoder_getMinimumStride}, which will now return   *              a value based on this width.   * @param height Height of the output (prior to cropping). - * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success - *         - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the AImageDecoder - *           pointer is null, width or height is <= 0, or any existing crop is - *           not contained by the image dimensions. + * @return an enum describing whether the call succeeded. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or + *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the {@link AImageDecoder} + *         pointer is null, width or height is <= 0, or any existing crop is + *         not contained by the new image dimensions.   */  int AImageDecoder_setTargetSize(AImageDecoder*, int32_t width, int32_t height) __INTRODUCED_IN(30); @@ -213,10 +259,11 @@ int AImageDecoder_setTargetSize(AImageDecoder*, int32_t width, int32_t height) _   *                   1/2 of the original dimensions, with 1/4 the number of   *                   pixels.   * @param width Out parameter for the width sampled by sampleSize, and rounded - *              direction that the decoder can do most efficiently. + *              in the direction that the decoder can do most efficiently.   * @param height Out parameter for the height sampled by sampleSize, and rounded - *               direction that the decoder can do most efficiently. - * @return ANDROID_IMAGE_DECODER result code. + *               in the direction that the decoder can do most efficiently. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or + *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} for bad input.   */  int AImageDecoder_computeSampledSize(const AImageDecoder*, int sampleSize,                                       int32_t* width, int32_t* height) __INTRODUCED_IN(30); @@ -234,18 +281,21 @@ int AImageDecoder_computeSampledSize(const AImageDecoder*, int sampleSize,   *             value based on the width of the crop. An empty ARect -   *             specifically { 0, 0, 0, 0 } - may be used to remove the cropping   *             behavior. Any other empty or unsorted ARects will result in - *             returning ANDROID_IMAGE_DECODER_BAD_PARAMETER. - * @return - {@link ANDROID_IMAGE_DECODER_SUCCESS} on success - *         - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the AImageDecoder - *           pointer is null or the crop is not contained by the image - *           dimensions. + *             returning {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}. + * @return an enum describing whether the call succeeded. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or + *         {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER} if the {@link AImageDecoder} + *         pointer is null or the crop is not contained by the image + *         dimensions.   */  int AImageDecoder_setCrop(AImageDecoder*, ARect crop) __INTRODUCED_IN(30); +struct AImageDecoderHeaderInfo;  /** - * Opaque handle for reading header info. + * Opaque handle for representing information about the encoded image. It can + * be passed to methods like {@link AImageDecoderHeaderInfo_getWidth} and + * {@link AImageDecoderHeaderInfo_getHeight}.   */ -struct AImageDecoderHeaderInfo;  typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;  /** @@ -258,12 +308,16 @@ const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(          const AImageDecoder*) __INTRODUCED_IN(30);  /** - * Report the native width of the encoded image. + * Report the native width of the encoded image. This is also the logical + * pixel width of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size.   */  int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);  /** - * Report the native height of the encoded image. + * Report the native height of the encoded image. This is also the logical + * pixel height of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size.   */  int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); @@ -277,7 +331,7 @@ const char* AImageDecoderHeaderInfo_getMimeType(  /**   * Report the {@link AndroidBitmapFormat} the AImageDecoder will decode to - * by default. AImageDecoder will try to choose one that is sensible + * by default. {@link AImageDecoder} will try to choose one that is sensible   * for the image and the system. Note that this does not indicate the   * encoded format of the image.   */ @@ -285,18 +339,17 @@ int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(          const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);  /** - * Report how the AImageDecoder will handle alpha by default. If the image + * Report how the {@link AImageDecoder} will handle alpha by default. If the image   * contains no alpha (according to its header), this will return   * {@link ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE}. If the image may contain alpha, - * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}. - * - * For animated images only the opacity of the first frame is reported. + * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}, because + * {@link AImageDecoder_decodeImage} will premultiply pixels by default.   */  int AImageDecoderHeaderInfo_getAlphaFlags(          const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);  /** - * Report the dataspace the AImageDecoder will decode to by default. + * Report the dataspace the {@link AImageDecoder} will decode to by default.   * AImageDecoder will try to choose one that is sensible for the   * image and the system. Note that this may not exactly match the ICC   * profile (or other color information) stored in the encoded image. @@ -315,26 +368,35 @@ int32_t AImageDecoderHeaderInfo_getDataSpace(          const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30);  /** - * Return the minimum stride that can be used, taking the specified - * (or default) (possibly scaled) width, crop rect and - * {@link AndroidBitmapFormat} into account. + * Return the minimum stride that can be used in + * {@link AImageDecoder_decodeImage). + * + * This stride provides no padding, meaning it will be exactly equal to the + * width times the number of bytes per pixel for the {@link AndroidBitmapFormat} + * being used. + * + * If the output is scaled (via {@link AImageDecoder_setTargetSize}) and/or + * cropped (via {@link AImageDecoder_setCrop}), this takes those into account.   */  size_t AImageDecoder_getMinimumStride(AImageDecoder*) __INTRODUCED_IN(30);  /** - * Decode the image into pixels, using the settings of the AImageDecoder. + * Decode the image into pixels, using the settings of the {@link AImageDecoder}.   *   * @param decoder Opaque object representing the decoder.   * @param pixels On success, will be filled with the result - *               of the decode. Must be large enough to fit |size| bytes. + *               of the decode. Must be large enough to hold |size| bytes.   * @param stride Width in bytes of a single row. Must be at least - *               {@link AImageDecoder_getMinimumStride}. + *               {@link AImageDecoder_getMinimumStride} and a multiple of the + *               bytes per pixel of the {@link AndroidBitmapFormat}.   * @param size Size of the pixel buffer in bytes. Must be at least   *             stride * (height - 1) + - *             {@link AImageDecoder_getMinimumStride}. Must also be a multiple - *             of the bytes per pixel of the {@link AndroidBitmapFormat}. + *             {@link AImageDecoder_getMinimumStride}.   * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success, or an error code   *         from the same enum describing the failure. + *         {@link ANDROID_IMAGE_DECODER_INCOMPLETE} or + *         {@link ANDROID_IMAGE_DECODER_ERROR} means that a partial image was + *         decoded, and undecoded lines have been initialized to all zeroes.   */  int AImageDecoder_decodeImage(AImageDecoder* decoder,                                void* pixels, size_t stride, diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl index a7a7292125..618f88c66d 100644 --- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl +++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl @@ -87,4 +87,7 @@ interface IPackageManagerNative {       * package.       */      @utf8InCpp String getModuleMetadataPackageName(); + +    /* Returns the names of all packages. */ +    @utf8InCpp String[] getAllPackages();  } diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 4e62da79ea..e2f5d31d00 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -31,6 +31,68 @@ using namespace std::chrono_literals;  namespace android { +void BLASTBufferItemConsumer::onDisconnect() { +    Mutex::Autolock lock(mFrameEventHistoryMutex); +    mPreviouslyConnected = mCurrentlyConnected; +    mCurrentlyConnected = false; +    if (mPreviouslyConnected) { +        mDisconnectEvents.push(mCurrentFrameNumber); +    } +    mFrameEventHistory.onDisconnect(); +} + +void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, +                                                       FrameEventHistoryDelta* outDelta) { +    Mutex::Autolock lock(mFrameEventHistoryMutex); +    if (newTimestamps) { +        // BufferQueueProducer only adds a new timestamp on +        // queueBuffer +        mCurrentFrameNumber = newTimestamps->frameNumber; +        mFrameEventHistory.addQueue(*newTimestamps); +    } +    if (outDelta) { +        // frame event histories will be processed +        // only after the producer connects and requests +        // deltas for the first time.  Forward this intent +        // to SF-side to turn event processing back on +        mPreviouslyConnected = mCurrentlyConnected; +        mCurrentlyConnected = true; +        mFrameEventHistory.getAndResetDelta(outDelta); +    } +} + +void BLASTBufferItemConsumer::updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, +                                                    const sp<Fence>& glDoneFence, +                                                    const sp<Fence>& presentFence, +                                                    const sp<Fence>& prevReleaseFence, +                                                    CompositorTiming compositorTiming, +                                                    nsecs_t latchTime, nsecs_t dequeueReadyTime) { +    Mutex::Autolock lock(mFrameEventHistoryMutex); + +    // if the producer is not connected, don't bother updating, +    // the next producer that connects won't access this frame event +    if (!mCurrentlyConnected) return; +    std::shared_ptr<FenceTime> glDoneFenceTime = std::make_shared<FenceTime>(glDoneFence); +    std::shared_ptr<FenceTime> presentFenceTime = std::make_shared<FenceTime>(presentFence); +    std::shared_ptr<FenceTime> releaseFenceTime = std::make_shared<FenceTime>(prevReleaseFence); + +    mFrameEventHistory.addLatch(frameNumber, latchTime); +    mFrameEventHistory.addRelease(frameNumber, dequeueReadyTime, std::move(releaseFenceTime)); +    mFrameEventHistory.addPreComposition(frameNumber, refreshStartTime); +    mFrameEventHistory.addPostComposition(frameNumber, glDoneFenceTime, presentFenceTime, +                                          compositorTiming); +} + +void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) { +    bool disconnect = false; +    Mutex::Autolock lock(mFrameEventHistoryMutex); +    while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) { +        disconnect = true; +        mDisconnectEvents.pop(); +    } +    if (needsDisconnect != nullptr) *needsDisconnect = disconnect; +} +  BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)        : mSurfaceControl(surface),          mWidth(width), @@ -39,7 +101,7 @@ BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width,      BufferQueue::createBufferQueue(&mProducer, &mConsumer);      mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS);      mBufferItemConsumer = -            new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true); +            new BLASTBufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);      static int32_t id = 0;      auto name = std::string("BLAST Consumer") + std::to_string(id);      id++; @@ -79,11 +141,21 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence      std::unique_lock _lock{mMutex};      ATRACE_CALL(); +    if (!stats.empty()) { +        mTransformHint = stats[0].transformHint; +        mBufferItemConsumer->setTransformHint(mTransformHint); +        mBufferItemConsumer->updateFrameTimestamps(stats[0].frameEventStats.frameNumber, +                                                   stats[0].frameEventStats.refreshStartTime, +                                                   stats[0].frameEventStats.gpuCompositionDoneFence, +                                                   stats[0].presentFence, +                                                   stats[0].previousReleaseFence, +                                                   stats[0].frameEventStats.compositorTiming, +                                                   stats[0].latchTime, +                                                   stats[0].frameEventStats.dequeueReadyTime); +    }      if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) { -        if (stats.size() > 0) { +        if (!stats.empty()) {              mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence; -            mTransformHint = stats[0].transformHint; -            mBufferItemConsumer->setTransformHint(mTransformHint);          } else {              ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");              mPendingReleaseItem.releaseFence = nullptr; @@ -144,6 +216,14 @@ void BLASTBufferQueue::processNextBufferLocked() {      mNumAcquired++;      mSubmitted.push(bufferItem); +    bool needsDisconnect = false; +    mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect); + +    // if producer disconnected before, notify SurfaceFlinger +    if (needsDisconnect) { +        t->notifyProducerDisconnect(mSurfaceControl); +    } +      // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.      incStrong((void*)transactionCallbackThunk); diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index e5e25aa50f..69f7894d07 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -30,6 +30,66 @@ enum class Tag : uint32_t {  } // Anonymous namespace +status_t FrameEventHistoryStats::writeToParcel(Parcel* output) const { +    status_t err = output->writeUint64(frameNumber); +    if (err != NO_ERROR) return err; + +    if (gpuCompositionDoneFence) { +        err = output->writeBool(true); +        if (err != NO_ERROR) return err; + +        err = output->write(*gpuCompositionDoneFence); +    } else { +        err = output->writeBool(false); +    } +    if (err != NO_ERROR) return err; + +    err = output->writeInt64(compositorTiming.deadline); +    if (err != NO_ERROR) return err; + +    err = output->writeInt64(compositorTiming.interval); +    if (err != NO_ERROR) return err; + +    err = output->writeInt64(compositorTiming.presentLatency); +    if (err != NO_ERROR) return err; + +    err = output->writeInt64(refreshStartTime); +    if (err != NO_ERROR) return err; + +    err = output->writeInt64(dequeueReadyTime); +    return err; +} + +status_t FrameEventHistoryStats::readFromParcel(const Parcel* input) { +    status_t err = input->readUint64(&frameNumber); +    if (err != NO_ERROR) return err; + +    bool hasFence = false; +    err = input->readBool(&hasFence); +    if (err != NO_ERROR) return err; + +    if (hasFence) { +        gpuCompositionDoneFence = new Fence(); +        err = input->read(*gpuCompositionDoneFence); +        if (err != NO_ERROR) return err; +    } + +    err = input->readInt64(&(compositorTiming.deadline)); +    if (err != NO_ERROR) return err; + +    err = input->readInt64(&(compositorTiming.interval)); +    if (err != NO_ERROR) return err; + +    err = input->readInt64(&(compositorTiming.presentLatency)); +    if (err != NO_ERROR) return err; + +    err = input->readInt64(&refreshStartTime); +    if (err != NO_ERROR) return err; + +    err = input->readInt64(&dequeueReadyTime); +    return err; +} +  status_t SurfaceStats::writeToParcel(Parcel* output) const {      status_t err = output->writeStrongBinder(surfaceControl);      if (err != NO_ERROR) { @@ -49,6 +109,11 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const {          err = output->writeBool(false);      }      err = output->writeUint32(transformHint); +    if (err != NO_ERROR) { +        return err; +    } + +    err = output->writeParcelable(eventStats);      return err;  } @@ -74,6 +139,11 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) {          }      }      err = input->readUint32(&transformHint); +    if (err != NO_ERROR) { +        return err; +    } + +    err = input->readParcelable(&eventStats);      return err;  } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 43bccf6c04..7017b7c8f3 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -222,8 +222,10 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener                  surfaceControlStats                          .emplace_back(callbacksMap[callbackId]                                                .surfaceControls[surfaceStats.surfaceControl], -                                      surfaceStats.acquireTime, surfaceStats.previousReleaseFence, -                                      surfaceStats.transformHint); +                                      transactionStats.latchTime, surfaceStats.acquireTime, +                                      transactionStats.presentFence, +                                      surfaceStats.previousReleaseFence, surfaceStats.transformHint, +                                      surfaceStats.eventStats);                  if (callbacksMap[callbackId].surfaceControls[surfaceStats.surfaceControl]) {                      callbacksMap[callbackId]                              .surfaceControls[surfaceStats.surfaceControl] @@ -1235,6 +1237,18 @@ SurfaceComposerClient::Transaction::addTransactionCompletedCallback(      return *this;  } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyProducerDisconnect( +        const sp<SurfaceControl>& sc) { +    layer_state_t* s = getLayerState(sc); +    if (!s) { +        mStatus = BAD_INDEX; +        return *this; +    } + +    s->what |= layer_state_t::eProducerDisconnect; +    return *this; +} +  SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(          const sp<SurfaceControl>& sc) {      layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index be429feade..d72eb5a632 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -33,6 +33,35 @@ namespace android {  class BufferItemConsumer; +class BLASTBufferItemConsumer : public BufferItemConsumer { +public: +    BLASTBufferItemConsumer(const sp<IGraphicBufferConsumer>& consumer, uint64_t consumerUsage, +                            int bufferCount, bool controlledByApp) +          : BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp), +            mCurrentlyConnected(false), +            mPreviouslyConnected(false) {} + +    void onDisconnect() override; +    void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, +                                  FrameEventHistoryDelta* outDelta) override +            REQUIRES(mFrameEventHistoryMutex); +    void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime, +                               const sp<Fence>& gpuCompositionDoneFence, +                               const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, +                               CompositorTiming compositorTiming, nsecs_t latchTime, +                               nsecs_t dequeueReadyTime) REQUIRES(mFrameEventHistoryMutex); +    void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect); + +private: +    uint64_t mCurrentFrameNumber = 0; + +    Mutex mFrameEventHistoryMutex; +    ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mFrameEventHistoryMutex); +    std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mFrameEventHistoryMutex); +    bool mCurrentlyConnected GUARDED_BY(mFrameEventHistoryMutex); +    bool mPreviouslyConnected GUARDED_BY(mFrameEventHistoryMutex); +}; +  class BLASTBufferQueue      : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener  { @@ -89,7 +118,7 @@ private:      sp<IGraphicBufferConsumer> mConsumer;      sp<IGraphicBufferProducer> mProducer; -    sp<BufferItemConsumer> mBufferItemConsumer; +    sp<BLASTBufferItemConsumer> mBufferItemConsumer;      SurfaceComposerClient::Transaction* mNextTransaction GUARDED_BY(mMutex);  }; diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h index 816dd2b176..4af86594fc 100644 --- a/libs/gui/include/gui/FrameTimestamps.h +++ b/libs/gui/include/gui/FrameTimestamps.h @@ -174,7 +174,6 @@ struct NewFrameEventsEntry {      std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};  }; -  // Used by the consumer to keep track of which fields it already sent to  // the producer.  class FrameEventDirtyFields { diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index 9c15225ac8..c58634b8a2 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -21,6 +21,7 @@  #include <binder/Parcelable.h>  #include <binder/SafeInterface.h> +#include <gui/FrameTimestamps.h>  #include <ui/Fence.h>  #include <utils/Timers.h> @@ -35,6 +36,27 @@ class ListenerCallbacks;  using CallbackId = int64_t; +class FrameEventHistoryStats : public Parcelable { +public: +    status_t writeToParcel(Parcel* output) const override; +    status_t readFromParcel(const Parcel* input) override; + +    FrameEventHistoryStats() = default; +    FrameEventHistoryStats(uint64_t fn, const sp<Fence>& gpuCompFence, CompositorTiming compTiming, +                           nsecs_t refreshTime, nsecs_t dequeueReadyTime) +          : frameNumber(fn), +            gpuCompositionDoneFence(gpuCompFence), +            compositorTiming(compTiming), +            refreshStartTime(refreshTime), +            dequeueReadyTime(dequeueReadyTime) {} + +    uint64_t frameNumber; +    sp<Fence> gpuCompositionDoneFence; +    CompositorTiming compositorTiming; +    nsecs_t refreshStartTime; +    nsecs_t dequeueReadyTime; +}; +  class SurfaceStats : public Parcelable {  public:      status_t writeToParcel(Parcel* output) const override; @@ -42,16 +64,18 @@ public:      SurfaceStats() = default;      SurfaceStats(const sp<IBinder>& sc, nsecs_t time, const sp<Fence>& prevReleaseFence, -                 uint32_t hint) +                 uint32_t hint, FrameEventHistoryStats frameEventStats)            : surfaceControl(sc),              acquireTime(time),              previousReleaseFence(prevReleaseFence), -            transformHint(hint) {} +            transformHint(hint), +            eventStats(frameEventStats) {}      sp<IBinder> surfaceControl;      nsecs_t acquireTime = -1;      sp<Fence> previousReleaseFence;      uint32_t transformHint = 0; +    FrameEventHistoryStats eventStats;  };  class TransactionStats : public Parcelable { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index c256a09c40..2d53b48475 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -102,6 +102,7 @@ struct layer_state_t {          eFrameRateSelectionPriority = 0x20'00000000,          eFrameRateChanged = 0x40'00000000,          eBackgroundBlurRadiusChanged = 0x80'00000000, +        eProducerDisconnect = 0x100'00000000,      };      layer_state_t() diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6eec2b7a91..d0bb6a39ec 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -52,17 +52,24 @@ class IRegionSamplingListener;  class Region;  struct SurfaceControlStats { -    SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t time, -                        const sp<Fence>& prevReleaseFence, uint32_t hint) +    SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime, nsecs_t acquireTime, +                        const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence, +                        uint32_t hint, FrameEventHistoryStats eventStats)            : surfaceControl(sc), -            acquireTime(time), +            latchTime(latchTime), +            acquireTime(acquireTime), +            presentFence(presentFence),              previousReleaseFence(prevReleaseFence), -            transformHint(hint) {} +            transformHint(hint), +            frameEventStats(eventStats) {}      sp<SurfaceControl> surfaceControl; +    nsecs_t latchTime = -1;      nsecs_t acquireTime = -1; +    sp<Fence> presentFence;      sp<Fence> previousReleaseFence;      uint32_t transformHint = 0; +    FrameEventHistoryStats frameEventStats;  };  using TransactionCompletedCallbackTakesContext = @@ -484,6 +491,9 @@ public:          Transaction& addTransactionCompletedCallback(                  TransactionCompletedCallbackTakesContext callback, void* callbackContext); +        // ONLY FOR BLAST ADAPTER +        Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc); +          // Detaches all child surfaces (and their children recursively)          // from their SurfaceControl.          // The child SurfaceControls will not throw exceptions or return errors, diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index a273914caf..b40eb14093 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -21,6 +21,7 @@  #include <android/hardware/graphics/common/1.2/types.h>  #include <gui/BufferQueueCore.h>  #include <gui/BufferQueueProducer.h> +#include <gui/FrameTimestamps.h>  #include <gui/IGraphicBufferProducer.h>  #include <gui/IProducerListener.h>  #include <gui/SurfaceComposerClient.h> @@ -647,4 +648,79 @@ TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_180) {  TEST_F(BLASTBufferQueueTransformTest, setTransform_ROT_270) {      test(ui::Transform::ROT_270);  } + +class BLASTFrameEventHistoryTest : public BLASTBufferQueueTest { +public: +    void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer, +                             nsecs_t* requestedPresentTime, nsecs_t* postedTime, +                             IGraphicBufferProducer::QueueBufferOutput* qbOutput, +                             bool getFrameTimestamps) { +        int slot; +        sp<Fence> fence; +        sp<GraphicBuffer> buf; +        auto ret = igbProducer->dequeueBuffer(&slot, &fence, mDisplayWidth, mDisplayHeight, +                                              PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_SW_WRITE_OFTEN, +                                              nullptr, nullptr); +        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); +        ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf)); + +        nsecs_t requestedTime = systemTime(); +        if (requestedPresentTime) *requestedPresentTime = requestedTime; +        IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN, +                                                       Rect(mDisplayWidth, mDisplayHeight), +                                                       NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, +                                                       Fence::NO_FENCE, /*sticky*/ 0, +                                                       getFrameTimestamps); +        if (postedTime) *postedTime = systemTime(); +        igbProducer->queueBuffer(slot, input, qbOutput); +    } +}; + +TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { +    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight); +    sp<IGraphicBufferProducer> igbProducer; +    ProducerFrameEventHistory history; +    setUpProducer(adapter, igbProducer); + +    IGraphicBufferProducer::QueueBufferOutput qbOutput; +    nsecs_t requestedPresentTimeA = 0; +    nsecs_t postedTimeA = 0; +    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true); +    history.applyDelta(qbOutput.frameTimestamps); + +    FrameEvents* events = nullptr; +    events = history.getFrame(1); +    ASSERT_NE(nullptr, events); +    ASSERT_EQ(1, events->frameNumber); +    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); +    ASSERT_GE(events->postedTime, postedTimeA); + +    adapter.waitForCallbacks(); + +    // queue another buffer so we query for frame event deltas +    nsecs_t requestedPresentTimeB = 0; +    nsecs_t postedTimeB = 0; +    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true); +    history.applyDelta(qbOutput.frameTimestamps); +    events = history.getFrame(1); +    ASSERT_NE(nullptr, events); + +    // frame number, requestedPresentTime, and postTime should not have changed +    ASSERT_EQ(1, events->frameNumber); +    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); +    ASSERT_GE(events->postedTime, postedTimeA); + +    ASSERT_GE(events->latchTime, postedTimeA); +    ASSERT_GE(events->dequeueReadyTime, events->latchTime); +    ASSERT_NE(nullptr, events->gpuCompositionDoneFence); +    ASSERT_NE(nullptr, events->displayPresentFence); +    ASSERT_NE(nullptr, events->releaseFence); + +    // we should also have gotten the initial values for the next frame +    events = history.getFrame(2); +    ASSERT_NE(nullptr, events); +    ASSERT_EQ(2, events->frameNumber); +    ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime); +    ASSERT_GE(events->postedTime, postedTimeB); +}  } // namespace android diff --git a/services/gpuservice/GpuService.h b/services/gpuservice/GpuService.h index 208a627f20..b3e34d559e 100644 --- a/services/gpuservice/GpuService.h +++ b/services/gpuservice/GpuService.h @@ -25,22 +25,11 @@  #include <mutex>  #include <vector> -#include <unordered_map>  namespace android {  class GpuStats; -struct MemoryStruct { -  int64_t gpuMemory; -  int64_t mappedMemory; -  int64_t ionMemory; -}; - -// A map that keeps track of how much memory of each type is allocated by every process. -// Format: map[pid][memoryType] = MemoryStruct()' -using GpuMemoryMap = std::unordered_map<int32_t, std::unordered_map<std::string, MemoryStruct>>; -  class GpuService : public BnGpuService, public PriorityDumper {  public:      static const char* const SERVICE_NAME ANDROID_API; @@ -80,8 +69,6 @@ private:      status_t doDump(int fd, const Vector<String16>& args, bool asProto); -    status_t getQCommGpuMemoryInfo(GpuMemoryMap* memories, std::string* result, int32_t dumpPid) const; -      /*       * Attributes       */ diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp index 1c9a4af72b..5246c78866 100644 --- a/services/sensorservice/Android.bp +++ b/services/sensorservice/Android.bp @@ -42,6 +42,7 @@ cc_library_shared {          "libbinder",          "libsensor",          "libsensorprivacy", +        "libprotoutil",          "libcrypto",          "libbase",          "libhidlbase", @@ -52,6 +53,8 @@ cc_library_shared {      static_libs: ["android.hardware.sensors@1.0-convert"], +    generated_headers: ["framework-cppstream-protos"], +      // our public headers depend on libsensor and libsensorprivacy      export_shared_lib_headers: ["libsensor", "libsensorprivacy"],  } diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp index 207b09711a..d7ca6e1dbf 100644 --- a/services/sensorservice/RecentEventLogger.cpp +++ b/services/sensorservice/RecentEventLogger.cpp @@ -17,6 +17,8 @@  #include "RecentEventLogger.h"  #include "SensorServiceUtils.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <utils/Timers.h>  #include <inttypes.h> @@ -84,6 +86,40 @@ std::string RecentEventLogger::dump() const {      return std::string(buffer.string());  } +/** + * Dump debugging information as android.service.SensorEventsProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void RecentEventLogger::dump(util::ProtoOutputStream* proto) const { +    using namespace service::SensorEventsProto; +    std::lock_guard<std::mutex> lk(mLock); + +    proto->write(RecentEventsLog::RECENT_EVENTS_COUNT, int(mRecentEvents.size())); +    for (int i = mRecentEvents.size() - 1; i >= 0; --i) { +        const auto& ev = mRecentEvents[i]; +        const uint64_t token = proto->start(RecentEventsLog::EVENTS); +        proto->write(Event::TIMESTAMP_SEC, float(ev.mEvent.timestamp) / 1e9f); +        proto->write(Event::WALL_TIMESTAMP_MS, ev.mWallTime.tv_sec * 1000LL +                + ns2ms(ev.mWallTime.tv_nsec)); + +        if (mMaskData) { +            proto->write(Event::MASKED, true); +        } else { +            if (mSensorType == SENSOR_TYPE_STEP_COUNTER) { +                proto->write(Event::INT64_DATA, int64_t(ev.mEvent.u64.step_counter)); +            } else { +                for (size_t k = 0; k < mEventSize; ++k) { +                    proto->write(Event::FLOAT_ARRAY, ev.mEvent.data[k]); +                } +            } +        } +        proto->end(token); +    } +} +  void RecentEventLogger::setFormat(std::string format) {      if (format == "mask_data" ) {          mMaskData = true; diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h index 67378b7dd6..3a2ae77fc8 100644 --- a/services/sensorservice/RecentEventLogger.h +++ b/services/sensorservice/RecentEventLogger.h @@ -48,6 +48,7 @@ public:      // Dumpable interface      virtual std::string dump() const override; +    virtual void dump(util::ProtoOutputStream* proto) const override;      virtual void setFormat(std::string format) override;  protected: diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index c7a8f5bee3..33f940fe80 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -21,6 +21,8 @@  #include "SensorService.h"  #include <android-base/logging.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <sensors/convert.h>  #include <cutils/atomic.h>  #include <utils/Errors.h> @@ -39,6 +41,7 @@ using android::hardware::sensors::V2_0::WakeLockQueueFlagBits;  using android::hardware::hidl_vec;  using android::hardware::Return;  using android::SensorDeviceUtils::HidlServiceRegistrationWaiter; +using android::util::ProtoOutputStream;  namespace android {  // --------------------------------------------------------------------------- @@ -396,6 +399,43 @@ std::string SensorDevice::dump() const {      return result.string();  } +/** + * Dump debugging information as android.service.SensorDeviceProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorDevice::dump(ProtoOutputStream* proto) const { +    using namespace service::SensorDeviceProto; +    if (mSensors == nullptr) { +        proto->write(INITIALIZED , false); +        return; +    } +    proto->write(INITIALIZED , true); +    proto->write(TOTAL_SENSORS , int(mSensorList.size())); +    proto->write(ACTIVE_SENSORS , int(mActivationCount.size())); + +    Mutex::Autolock _l(mLock); +    for (const auto & s : mSensorList) { +        int32_t handle = s.handle; +        const Info& info = mActivationCount.valueFor(handle); +        if (info.numActiveClients() == 0) continue; + +        uint64_t token = proto->start(SENSORS); +        proto->write(SensorProto::HANDLE , handle); +        proto->write(SensorProto::ACTIVE_COUNT , int(info.batchParams.size())); +        for (size_t j = 0; j < info.batchParams.size(); j++) { +            const BatchParams& params = info.batchParams[j]; +            proto->write(SensorProto::SAMPLING_PERIOD_MS , params.mTSample / 1e6f); +            proto->write(SensorProto::BATCHING_PERIOD_MS , params.mTBatch / 1e6f); +        } +        proto->write(SensorProto::SAMPLING_PERIOD_SELECTED , info.bestBatchParams.mTSample / 1e6f); +        proto->write(SensorProto::BATCHING_PERIOD_SELECTED , info.bestBatchParams.mTBatch / 1e6f); +        proto->end(token); +    } +} +  ssize_t SensorDevice::getSensorList(sensor_t const** list) {      *list = &mSensorList[0]; diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index d2c6994023..33aa7d64b0 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -123,7 +123,8 @@ public:      bool isSensorActive(int handle) const;      // Dumpable -    virtual std::string dump() const; +    virtual std::string dump() const override; +    virtual void dump(util::ProtoOutputStream* proto) const override;  private:      friend class Singleton<SensorDevice>; diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp index cd0ea5d22c..106efd6634 100644 --- a/services/sensorservice/SensorDirectConnection.cpp +++ b/services/sensorservice/SensorDirectConnection.cpp @@ -16,12 +16,16 @@  #include "SensorDevice.h"  #include "SensorDirectConnection.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <hardware/sensors.h>  #define UNUSED(x) (void)(x)  namespace android { +using util::ProtoOutputStream; +  SensorService::SensorDirectConnection::SensorDirectConnection(const sp<SensorService>& service,          uid_t uid, const sensors_direct_mem_t *mem, int32_t halChannelHandle,          const String16& opPackageName) @@ -64,6 +68,27 @@ void SensorService::SensorDirectConnection::dump(String8& result) const {      }  } +/** + * Dump debugging information as android.service.SensorDirectConnectionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorService::SensorDirectConnection::dump(ProtoOutputStream* proto) const { +    using namespace service::SensorDirectConnectionProto; +    Mutex::Autolock _l(mConnectionLock); +    proto->write(PACKAGE_NAME, std::string(String8(mOpPackageName).string())); +    proto->write(HAL_CHANNEL_HANDLE, getHalChannelHandle()); +    proto->write(NUM_SENSOR_ACTIVATED, int(mActivated.size())); +    for (auto &i : mActivated) { +        uint64_t token = proto->start(SENSORS); +        proto->write(SensorProto::SENSOR, i.first); +        proto->write(SensorProto::RATE, i.second); +        proto->end(token); +    } +} +  sp<BitTube> SensorService::SensorDirectConnection::getSensorChannel() const {      return nullptr;  } diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h index 5c398a8caa..ead08d3fb6 100644 --- a/services/sensorservice/SensorDirectConnection.h +++ b/services/sensorservice/SensorDirectConnection.h @@ -40,6 +40,7 @@ public:              const sensors_direct_mem_t *mem, int32_t halChannelHandle,              const String16& opPackageName);      void dump(String8& result) const; +    void dump(util::ProtoOutputStream* proto) const;      uid_t getUid() const { return mUid; }      int32_t getHalChannelHandle() const;      bool isEquivalent(const sensors_direct_mem_t *mem) const; diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp index 0e409409f2..9a13c00664 100644 --- a/services/sensorservice/SensorEventConnection.cpp +++ b/services/sensorservice/SensorEventConnection.cpp @@ -17,6 +17,8 @@  #include <sys/socket.h>  #include <utils/threads.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <sensor/SensorEventQueue.h>  #include "vec.h" @@ -110,6 +112,51 @@ void SensorService::SensorEventConnection::dump(String8& result) {  #endif  } +/** + * Dump debugging information as android.service.SensorEventConnectionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorService::SensorEventConnection::dump(util::ProtoOutputStream* proto) const { +    using namespace service::SensorEventConnectionProto; +    Mutex::Autolock _l(mConnectionLock); + +    if (!mService->isWhiteListedPackage(getPackageName())) { +        proto->write(OPERATING_MODE, OP_MODE_RESTRICTED); +    } else if (mDataInjectionMode) { +        proto->write(OPERATING_MODE, OP_MODE_DATA_INJECTION); +    } else { +        proto->write(OPERATING_MODE, OP_MODE_NORMAL); +    } +    proto->write(PACKAGE_NAME, std::string(mPackageName.string())); +    proto->write(WAKE_LOCK_REF_COUNT, int32_t(mWakeLockRefCount)); +    proto->write(UID, int32_t(mUid)); +    proto->write(CACHE_SIZE, int32_t(mCacheSize)); +    proto->write(MAX_CACHE_SIZE, int32_t(mMaxCacheSize)); +    for (size_t i = 0; i < mSensorInfo.size(); ++i) { +        const FlushInfo& flushInfo = mSensorInfo.valueAt(i); +        const uint64_t token = proto->start(FLUSH_INFOS); +        proto->write(FlushInfoProto::SENSOR_NAME, +                std::string(mService->getSensorName(mSensorInfo.keyAt(i)))); +        proto->write(FlushInfoProto::SENSOR_HANDLE, mSensorInfo.keyAt(i)); +        proto->write(FlushInfoProto::FIRST_FLUSH_PENDING, flushInfo.mFirstFlushPending); +        proto->write(FlushInfoProto::PENDING_FLUSH_EVENTS_TO_SEND, +                flushInfo.mPendingFlushEventsToSend); +        proto->end(token); +    } +#if DEBUG_CONNECTIONS +    proto->write(EVENTS_RECEIVED, mEventsReceived); +    proto->write(EVENTS_SENT, mEventsSent); +    proto->write(EVENTS_CACHE, mEventsSentFromCache); +    proto->write(EVENTS_DROPPED, mEventsReceived - (mEventsSentFromCache + mEventsSent + +            mCacheSize)); +    proto->write(TOTAL_ACKS_NEEDED, mTotalAcksNeeded); +    proto->write(TOTAL_ACKS_RECEIVED, mTotalAcksReceived); +#endif +} +  bool SensorService::SensorEventConnection::addSensor(int32_t handle) {      Mutex::Autolock _l(mConnectionLock);      sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle); diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h index fd881cbc0b..caf5d7c9d9 100644 --- a/services/sensorservice/SensorEventConnection.h +++ b/services/sensorservice/SensorEventConnection.h @@ -62,6 +62,7 @@ public:      bool removeSensor(int32_t handle);      void setFirstFlushPending(int32_t handle, bool value);      void dump(String8& result); +    void dump(util::ProtoOutputStream* proto) const;      bool needsWakeLock();      void resetWakeLockRefCount();      String8 getPackageName() const; diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp index 414f673271..e27b52b23e 100644 --- a/services/sensorservice/SensorFusion.cpp +++ b/services/sensorservice/SensorFusion.cpp @@ -18,6 +18,9 @@  #include "SensorFusion.h"  #include "SensorService.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> +  namespace android {  // --------------------------------------------------------------------------- @@ -183,7 +186,7 @@ int32_t SensorFusion::getMinDelay() const {      return mAcc.getMinDelay();  } -void SensorFusion::dump(String8& result) { +void SensorFusion::dump(String8& result) const {      const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]);      result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "              "q=< %g, %g, %g, %g > (%g), " @@ -235,5 +238,42 @@ void SensorFusion::dump(String8& result) {              fusion_nogyro.getBias().z);  } +void SensorFusion::dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const { +    using namespace service::SensorFusionProto::FusionProto; +    const Fusion& fusion(mFusions[mode]); +    proto->write(ENABLED, mEnabled[mode]); +    proto->write(NUM_CLIENTS, (int)mClients[mode].size()); +    proto->write(ESTIMATED_GYRO_RATE, mEstimatedGyroRate); +    proto->write(ATTITUDE_X, fusion.getAttitude().x); +    proto->write(ATTITUDE_Y, fusion.getAttitude().y); +    proto->write(ATTITUDE_Z, fusion.getAttitude().z); +    proto->write(ATTITUDE_W, fusion.getAttitude().w); +    proto->write(ATTITUDE_LENGTH, length(fusion.getAttitude())); +    proto->write(BIAS_X, fusion.getBias().x); +    proto->write(BIAS_Y, fusion.getBias().y); +    proto->write(BIAS_Z, fusion.getBias().z); +} + +/** + * Dump debugging information as android.service.SensorFusionProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorFusion::dump(util::ProtoOutputStream* proto) const { +    uint64_t token = proto->start(service::SensorFusionProto::FUSION_9AXIS); +    dumpFusion(FUSION_9AXIS, proto); +    proto->end(token); + +    token = proto->start(service::SensorFusionProto::FUSION_NOMAG); +    dumpFusion(FUSION_NOMAG, proto); +    proto->end(token); + +    token = proto->start(service::SensorFusionProto::FUSION_NOGYRO); +    dumpFusion(FUSION_NOGYRO, proto); +    proto->end(token); +} +  // ---------------------------------------------------------------------------  }; // namespace android diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h index 8c0fbf9a6e..66a72902cc 100644 --- a/services/sensorservice/SensorFusion.h +++ b/services/sensorservice/SensorFusion.h @@ -90,7 +90,9 @@ public:      float getPowerUsage(int mode=FUSION_9AXIS) const;      int32_t getMinDelay() const; -    void dump(String8& result); +    void dump(String8& result) const; +    void dump(util::ProtoOutputStream* proto) const; +    void dumpFusion(FUSION_MODE mode, util::ProtoOutputStream* proto) const;  }; diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp index aa306d885e..0ce32cc06f 100644 --- a/services/sensorservice/SensorList.cpp +++ b/services/sensorservice/SensorList.cpp @@ -16,6 +16,8 @@  #include "SensorList.h" +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <hardware/sensors.h>  #include <utils/String8.h> @@ -203,6 +205,64 @@ std::string SensorList::dump() const {      return std::string(result.string());  } +/** + * Dump debugging information as android.service.SensorListProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +void SensorList::dump(util::ProtoOutputStream* proto) const { +    using namespace service::SensorListProto; +    using namespace service::SensorListProto::SensorProto; + +    forEachSensor([&proto] (const Sensor& s) -> bool { +        const uint64_t token = proto->start(SENSORS); +        proto->write(HANDLE, s.getHandle()); +        proto->write(NAME, std::string(s.getName().string())); +        proto->write(VENDOR, std::string(s.getVendor().string())); +        proto->write(VERSION, s.getVersion()); +        proto->write(STRING_TYPE, std::string(s.getStringType().string())); +        proto->write(TYPE, s.getType()); +        proto->write(REQUIRED_PERMISSION, std::string(s.getRequiredPermission().size() ? +                s.getRequiredPermission().string() : "")); +        proto->write(FLAGS, int(s.getFlags())); +        switch (s.getReportingMode()) { +            case AREPORTING_MODE_CONTINUOUS: +                proto->write(REPORTING_MODE, RM_CONTINUOUS); +                break; +            case AREPORTING_MODE_ON_CHANGE: +                proto->write(REPORTING_MODE, RM_ON_CHANGE); +                break; +            case AREPORTING_MODE_ONE_SHOT: +                proto->write(REPORTING_MODE, RM_ONE_SHOT); +                break; +            case AREPORTING_MODE_SPECIAL_TRIGGER: +                proto->write(REPORTING_MODE, RM_SPECIAL_TRIGGER); +                break; +            default: +                proto->write(REPORTING_MODE, RM_UNKNOWN); +        } +        proto->write(MAX_DELAY_US, s.getMaxDelay()); +        proto->write(MIN_DELAY_US, s.getMinDelay()); +        proto->write(FIFO_MAX_EVENT_COUNT, int(s.getFifoMaxEventCount())); +        proto->write(FIFO_RESERVED_EVENT_COUNT, int(s.getFifoReservedEventCount())); +        proto->write(IS_WAKEUP, s.isWakeUpSensor()); +        proto->write(DATA_INJECTION_SUPPORTED, s.isDataInjectionSupported()); +        proto->write(IS_DYNAMIC, s.isDynamicSensor()); +        proto->write(HAS_ADDITIONAL_INFO, s.hasAdditionalInfo()); +        proto->write(HIGHEST_RATE_LEVEL, s.getHighestDirectReportRateLevel()); +        proto->write(ASHMEM, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_ASHMEM)); +        proto->write(GRALLOC, s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)); +        proto->write(MIN_VALUE, s.getMinValue()); +        proto->write(MAX_VALUE, s.getMaxValue()); +        proto->write(RESOLUTION, s.getResolution()); +        proto->write(POWER_USAGE, s.getPowerUsage()); +        proto->end(token); +        return true; +    }); +} +  SensorList::~SensorList() {  } diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h index 6b90ad99f9..8424b22ed2 100644 --- a/services/sensorservice/SensorList.h +++ b/services/sensorservice/SensorList.h @@ -71,6 +71,7 @@ public:      // Dumpable interface      virtual std::string dump() const override; +    virtual void dump(util::ProtoOutputStream* proto) const override;      virtual ~SensorList();  private: diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h index 5411515d49..a34a65bbdd 100644 --- a/services/sensorservice/SensorRegistrationInfo.h +++ b/services/sensorservice/SensorRegistrationInfo.h @@ -17,10 +17,14 @@  #ifndef ANDROID_SENSOR_REGISTRATION_INFO_H  #define ANDROID_SENSOR_REGISTRATION_INFO_H -#include "SensorServiceUtils.h" -#include <utils/Thread.h> +#include <ctime>  #include <iomanip>  #include <sstream> +#include <utils/Thread.h> + +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h> +#include "SensorServiceUtils.h"  namespace android { @@ -30,7 +34,7 @@ class SensorService::SensorRegistrationInfo : public SensorServiceUtil::Dumpable  public:      SensorRegistrationInfo() : mPackageName() {          mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN; -        mHour = mMin = mSec = INT8_MIN; +        mRealtimeSec = 0;          mActivated = false;      } @@ -47,25 +51,26 @@ public:          mPid = (thread != nullptr) ? thread->getCallingPid() : -1;          mUid = (thread != nullptr) ? thread->getCallingUid() : -1; -        time_t rawtime = time(nullptr); -        struct tm * timeinfo = localtime(&rawtime); -        mHour = static_cast<int8_t>(timeinfo->tm_hour); -        mMin = static_cast<int8_t>(timeinfo->tm_min); -        mSec = static_cast<int8_t>(timeinfo->tm_sec); +        timespec curTime; +        clock_gettime(CLOCK_REALTIME_COARSE, &curTime); +        mRealtimeSec = curTime.tv_sec;      }      static bool isSentinel(const SensorRegistrationInfo& info) { -       return (info.mHour == INT8_MIN && -               info.mMin == INT8_MIN && -               info.mSec == INT8_MIN); +       return (info.mSensorHandle == INT32_MIN && info.mRealtimeSec == 0);      }      // Dumpable interface      virtual std::string dump() const override { +        struct tm* timeinfo = localtime(&mRealtimeSec); +        const int8_t hour = static_cast<int8_t>(timeinfo->tm_hour); +        const int8_t min = static_cast<int8_t>(timeinfo->tm_min); +        const int8_t sec = static_cast<int8_t>(timeinfo->tm_sec); +          std::ostringstream ss; -        ss << std::setfill('0') << std::setw(2) << static_cast<int>(mHour) << ":" -           << std::setw(2) << static_cast<int>(mMin) << ":" -           << std::setw(2) << static_cast<int>(mSec) +        ss << std::setfill('0') << std::setw(2) << static_cast<int>(hour) << ":" +           << std::setw(2) << static_cast<int>(min) << ":" +           << std::setw(2) << static_cast<int>(sec)             << (mActivated ? " +" : " -")             << " 0x" << std::hex << std::setw(8) << mSensorHandle << std::dec             << std::setfill(' ') << " pid=" << std::setw(5) << mPid @@ -77,6 +82,25 @@ public:          return ss.str();      } +    /** +     * Dump debugging information as android.service.SensorRegistrationInfoProto protobuf message +     * using ProtoOutputStream. +     * +     * See proto definition and some notes about ProtoOutputStream in +     * frameworks/base/core/proto/android/service/sensor_service.proto +     */ +    virtual void dump(util::ProtoOutputStream* proto) const override { +        using namespace service::SensorRegistrationInfoProto; +        proto->write(TIMESTAMP_SEC, int64_t(mRealtimeSec)); +        proto->write(SENSOR_HANDLE, mSensorHandle); +        proto->write(PACKAGE_NAME, std::string(mPackageName.string())); +        proto->write(PID, int32_t(mPid)); +        proto->write(UID, int32_t(mUid)); +        proto->write(SAMPLING_RATE_US, mSamplingRateUs); +        proto->write(MAX_REPORT_LATENCY_US, mMaxReportLatencyUs); +        proto->write(ACTIVATED, mActivated); +    } +  private:      int32_t mSensorHandle;      String8 mPackageName; @@ -85,8 +109,7 @@ private:      int64_t mSamplingRateUs;      int64_t mMaxReportLatencyUs;      bool mActivated; -    int8_t mHour, mMin, mSec; - +    time_t mRealtimeSec;  };  } // namespace android; diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index c2e1204b87..e803c9ad7e 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -14,6 +14,8 @@   * limitations under the License.   */  #include <android/content/pm/IPackageManagerNative.h> +#include <android/util/ProtoOutputStream.h> +#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>  #include <binder/ActivityManager.h>  #include <binder/BinderService.h>  #include <binder/IServiceManager.h> @@ -404,6 +406,8 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) {                  // Transition to data injection mode supported only from NORMAL mode.                  return INVALID_OPERATION;              } +        } else if (args.size() == 1 && args[0] == String16("--proto")) { +            return dumpProtoLocked(fd, &connLock);          } else if (!mSensors.hasAnySensor()) {              result.append("No Sensors on the device\n");              result.appendFormat("devInitCheck : %d\n", SensorDevice::getInstance().initCheck()); @@ -506,6 +510,124 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) {      return NO_ERROR;  } +/** + * Dump debugging information as android.service.SensorServiceProto protobuf message using + * ProtoOutputStream. + * + * See proto definition and some notes about ProtoOutputStream in + * frameworks/base/core/proto/android/service/sensor_service.proto + */ +status_t SensorService::dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const { +    using namespace service::SensorServiceProto; +    util::ProtoOutputStream proto; +    const bool privileged = IPCThreadState::self()->getCallingUid() == 0; + +    timespec curTime; +    clock_gettime(CLOCK_REALTIME, &curTime); +    proto.write(CURRENT_TIME_MS, curTime.tv_sec * 1000 + ns2ms(curTime.tv_nsec)); + +    // Write SensorDeviceProto +    uint64_t token = proto.start(SENSOR_DEVICE); +    SensorDevice::getInstance().dump(&proto); +    proto.end(token); + +    // Write SensorListProto +    token = proto.start(SENSORS); +    mSensors.dump(&proto); +    proto.end(token); + +    // Write SensorFusionProto +    token = proto.start(FUSION_STATE); +    SensorFusion::getInstance().dump(&proto); +    proto.end(token); + +    // Write SensorEventsProto +    token = proto.start(SENSOR_EVENTS); +    for (auto&& i : mRecentEvent) { +        sp<SensorInterface> s = mSensors.getInterface(i.first); +        if (!i.second->isEmpty()) { +            i.second->setFormat(privileged || s->getSensor().getRequiredPermission().isEmpty() ? +                    "normal" : "mask_data"); +            const uint64_t mToken = proto.start(service::SensorEventsProto::RECENT_EVENTS_LOGS); +            proto.write(service::SensorEventsProto::RecentEventsLog::NAME, +                    std::string(s->getSensor().getName().string())); +            i.second->dump(&proto); +            proto.end(mToken); +        } +    } +    proto.end(token); + +    // Write ActiveSensorProto +    SensorDevice& dev = SensorDevice::getInstance(); +    for (size_t i=0 ; i<mActiveSensors.size() ; i++) { +        int handle = mActiveSensors.keyAt(i); +        if (dev.isSensorActive(handle)) { +            token = proto.start(ACTIVE_SENSORS); +            proto.write(service::ActiveSensorProto::NAME, +                    std::string(getSensorName(handle).string())); +            proto.write(service::ActiveSensorProto::HANDLE, handle); +            proto.write(service::ActiveSensorProto::NUM_CONNECTIONS, +                    int(mActiveSensors.valueAt(i)->getNumConnections())); +            proto.end(token); +        } +    } + +    proto.write(SOCKET_BUFFER_SIZE, int(mSocketBufferSize)); +    proto.write(SOCKET_BUFFER_SIZE_IN_EVENTS, int(mSocketBufferSize / sizeof(sensors_event_t))); +    proto.write(WAKE_LOCK_ACQUIRED, mWakeLockAcquired); + +    switch(mCurrentOperatingMode) { +        case NORMAL: +            proto.write(OPERATING_MODE, OP_MODE_NORMAL); +            break; +        case RESTRICTED: +            proto.write(OPERATING_MODE, OP_MODE_RESTRICTED); +            proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string())); +            break; +        case DATA_INJECTION: +            proto.write(OPERATING_MODE, OP_MODE_DATA_INJECTION); +            proto.write(WHITELISTED_PACKAGE, std::string(mWhiteListedPackage.string())); +            break; +        default: +            proto.write(OPERATING_MODE, OP_MODE_UNKNOWN); +    } +    proto.write(SENSOR_PRIVACY, mSensorPrivacyPolicy->isSensorPrivacyEnabled()); + +    // Write repeated SensorEventConnectionProto +    const auto& activeConnections = connLock->getActiveConnections(); +    for (size_t i = 0; i < activeConnections.size(); i++) { +        token = proto.start(ACTIVE_CONNECTIONS); +        activeConnections[i]->dump(&proto); +        proto.end(token); +    } + +    // Write repeated SensorDirectConnectionProto +    const auto& directConnections = connLock->getDirectConnections(); +    for (size_t i = 0 ; i < directConnections.size() ; i++) { +        token = proto.start(DIRECT_CONNECTIONS); +        directConnections[i]->dump(&proto); +        proto.end(token); +    } + +    // Write repeated SensorRegistrationInfoProto +    const int startIndex = mNextSensorRegIndex; +    int curr = startIndex; +    do { +        const SensorRegistrationInfo& reg_info = mLastNSensorRegistrations[curr]; +        if (SensorRegistrationInfo::isSentinel(reg_info)) { +            // Ignore sentinel, proceed to next item. +            curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE; +            continue; +        } +        token = proto.start(PREVIOUS_REGISTRATIONS); +        reg_info.dump(&proto); +        proto.end(token); +        curr = (curr + 1 + SENSOR_REGISTRATIONS_BUF_SIZE) % SENSOR_REGISTRATIONS_BUF_SIZE; +    } while (startIndex != curr); + +    return proto.flush(fd) ? OK : UNKNOWN_ERROR; +} +  void SensorService::disableAllSensors() {      ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);      disableAllSensorsLocked(&connLock); diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index fa23da0468..7d17ddabf1 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -286,6 +286,7 @@ private:      virtual int setOperationParameter(              int32_t handle, int32_t type, const Vector<float> &floats, const Vector<int32_t> &ints);      virtual status_t dump(int fd, const Vector<String16>& args); +    status_t dumpProtoLocked(int fd, ConnectionSafeAutolock* connLock) const;      String8 getSensorName(int handle) const;      bool isVirtualSensor(int handle) const;      sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const; diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h index 1558feb75e..49457cf287 100644 --- a/services/sensorservice/SensorServiceUtils.h +++ b/services/sensorservice/SensorServiceUtils.h @@ -21,11 +21,17 @@  #include <string>  namespace android { + +namespace util { +class ProtoOutputStream; +} +  namespace SensorServiceUtil {  class Dumpable {  public:      virtual std::string dump() const = 0; +    virtual void dump(util::ProtoOutputStream*) const {}      virtual void setFormat(std::string ) {}      virtual ~Dumpable() {}  }; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 29688dac63..923a81c093 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -115,6 +115,7 @@ void BufferStateLayer::setTransformHint(uint32_t orientation) const {  void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {      for (const auto& handle : mDrawingState.callbackHandles) {          handle->transformHint = mTransformHint; +        handle->dequeueReadyTime = dequeueReadyTime;      }      mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles( @@ -133,6 +134,14 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) {      }  } +void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, +                                                 const CompositorTiming& compositorTiming) { +    for (const auto& handle : mDrawingState.callbackHandles) { +        handle->gpuCompositionDoneFence = glDoneFence; +        handle->compositorTiming = compositorTiming; +    } +} +  bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {      if (getSidebandStreamChanged() || getAutoRefresh()) {          return true; @@ -149,6 +158,8 @@ bool BufferStateLayer::willPresentCurrentTransaction() const {          !mLayerDetached;  } +/* TODO: vhau uncomment once deferred transaction migration complete in + * WindowManager  void BufferStateLayer::pushPendingState() {      if (!mCurrentState.modified) {          return; @@ -156,13 +167,12 @@ void BufferStateLayer::pushPendingState() {      mPendingStates.push_back(mCurrentState);      ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());  } +*/  bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { -    const bool stateUpdateAvailable = !mPendingStates.empty(); -    while (!mPendingStates.empty()) { -        popPendingState(stateToCommit); -    } -    mCurrentStateModified = stateUpdateAvailable && mCurrentState.modified; +    mCurrentStateModified = mCurrentState.modified; +    bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit); +    mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified;      mCurrentState.modified = false;      return stateUpdateAvailable;  } @@ -244,14 +254,15 @@ bool BufferStateLayer::setFrame(const Rect& frame) {      return true;  } -bool BufferStateLayer::updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime, -                                               nsecs_t desiredPresentTime) { +bool BufferStateLayer::addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime, +                                     nsecs_t desiredPresentTime) {      Mutex::Autolock lock(mFrameEventHistoryMutex);      mAcquireTimeline.updateSignalTimes();      std::shared_ptr<FenceTime> acquireFenceTime =              std::make_shared<FenceTime>((acquireFence ? acquireFence : Fence::NO_FENCE));      NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime,                                           acquireFenceTime}; +    mFrameEventHistory.setProducerWantsEvents();      mFrameEventHistory.addQueue(newTimestamps);      return true;  } @@ -276,12 +287,12 @@ bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence      mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());      mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mCurrentState.frameNumber,                                             postTime, FrameTracer::FrameEvent::POST); +    desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;      mCurrentState.desiredPresentTime = desiredPresentTime; -    mFlinger->mScheduler->recordLayerHistory(this, -                                             desiredPresentTime <= 0 ? 0 : desiredPresentTime); +    mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); -    updateFrameEventHistory(acquireFence, postTime, desiredPresentTime); +    addFrameEvent(acquireFence, postTime, desiredPresentTime);      return true;  } @@ -446,6 +457,13 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co      return mCurrentState.desiredPresentTime <= expectedPresentTime;  } +bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { +    for (const auto& handle : mDrawingState.callbackHandles) { +        handle->refreshStartTime = refreshStartTime; +    } +    return BufferLayer::onPreComposition(refreshStartTime); +} +  uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const {      return mDrawingState.frameNumber;  } @@ -529,6 +547,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse      for (auto& handle : mDrawingState.callbackHandles) {          handle->latchTime = latchTime; +        handle->frameNumber = mDrawingState.frameNumber;      }      if (!SyncFeatures::getInstance().useNativeFenceSync()) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 57ff8bc00d..6ee58024f0 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -45,12 +45,17 @@ public:      void setTransformHint(uint32_t orientation) const override;      void releasePendingBuffer(nsecs_t dequeueReadyTime) override; +    void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, +                                   const CompositorTiming& compositorTiming) override; +      bool shouldPresentNow(nsecs_t expectedPresentTime) const override;      uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {          return flags;      } -    void pushPendingState() override; +    /*TODO:vhau return to using BufferStateLayer override once WM +     * has removed deferred transactions! +    void pushPendingState() override;*/      bool applyPendingStates(Layer::State* stateToCommit) override;      uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; } @@ -78,6 +83,8 @@ public:      bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;      bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;      void forceSendCallbacks() override; +    bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime, +                       nsecs_t requestedPresentTime) override;      // Override to ignore legacy layer state properties that are not used by BufferStateLayer      bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } @@ -104,6 +111,7 @@ public:      // -----------------------------------------------------------------------      bool fenceHasSignaled() const override;      bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; +    bool onPreComposition(nsecs_t refreshStartTime) override;  protected:      void gatherBufferInfo() override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 810e0af47f..de4a08070c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -372,6 +372,10 @@ public:          return false;      };      virtual void forceSendCallbacks() {} +    virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/, +                               nsecs_t /*requestedPresentTime*/) { +        return false; +    }      virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);      virtual bool setColorSpaceAgnostic(const bool agnostic);      bool setShadowRadius(float shadowRadius); @@ -596,6 +600,8 @@ public:      // If a buffer was replaced this frame, release the former buffer      virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } +    virtual void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& /*glDoneFence*/, +                                           const CompositorTiming& /*compositorTiming*/) {}      /*       * doTransaction - process the transaction. This is a good place to figure       * out which attributes of the surface have changed. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 33d85cb420..c125b2c75b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2037,12 +2037,10 @@ void SurfaceFlinger::postComposition()      ATRACE_CALL();      ALOGV("postComposition"); -    // Release any buffers which were replaced this frame      nsecs_t dequeueReadyTime = systemTime();      for (auto& layer : mLayersWithQueuedFrames) {          layer->releasePendingBuffer(dequeueReadyTime);      } -      // |mStateLock| not needed as we are on the main thread      const auto displayDevice = getDefaultDisplayDeviceLocked(); @@ -3349,6 +3347,11 @@ uint32_t SurfaceFlinger::setClientStateLocked(          layer->pushPendingState();      } +    // Only set by BLAST adapter layers +    if (what & layer_state_t::eProducerDisconnect) { +        layer->onDisconnect(); +    } +      if (what & layer_state_t::ePositionChanged) {          if (layer->setPosition(s.x, s.y)) {              flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index daa67ae043..0cdff8f380 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -237,9 +237,13 @@ status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>&      // destroyed the client side is dead and there won't be anyone to send the callback to.      sp<IBinder> surfaceControl = handle->surfaceControl.promote();      if (surfaceControl) { +        FrameEventHistoryStats eventStats(handle->frameNumber, +                                          handle->gpuCompositionDoneFence->getSnapshot().fence, +                                          handle->compositorTiming, handle->refreshStartTime, +                                          handle->dequeueReadyTime);          transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,                                                      handle->previousReleaseFence, -                                                    handle->transformHint); +                                                    handle->transformHint, eventStats);      }      return NO_ERROR;  } diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h index 12ea8fe7d0..f50147a1e9 100644 --- a/services/surfaceflinger/TransactionCompletedThread.h +++ b/services/surfaceflinger/TransactionCompletedThread.h @@ -45,6 +45,11 @@ public:      nsecs_t acquireTime = -1;      nsecs_t latchTime = -1;      uint32_t transformHint = 0; +    std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE}; +    CompositorTiming compositorTiming; +    nsecs_t refreshStartTime = 0; +    nsecs_t dequeueReadyTime = 0; +    uint64_t frameNumber = 0;  };  class TransactionCompletedThread { diff --git a/services/surfaceflinger/tests/utils/CallbackUtils.h b/services/surfaceflinger/tests/utils/CallbackUtils.h index 4e2b7c3543..1318debbba 100644 --- a/services/surfaceflinger/tests/utils/CallbackUtils.h +++ b/services/surfaceflinger/tests/utils/CallbackUtils.h @@ -121,8 +121,10 @@ private:          void verifySurfaceControlStats(const SurfaceControlStats& surfaceControlStats,                                         nsecs_t latchTime) const { -            const auto& [surfaceControl, acquireTime, previousReleaseFence, transformHint] = -                    surfaceControlStats; +            const auto& +                    [surfaceControl, latch, acquireTime, presentFence, previousReleaseFence, +                     transformHint, +                     frameEvents] = surfaceControlStats;              ASSERT_EQ(acquireTime > 0, mBufferResult == ExpectedResult::Buffer::ACQUIRED)                      << "bad acquire time";  |