/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

package com.facebook.imagepipeline.producers;

import com.facebook.common.internal.Preconditions;
import com.facebook.imagepipeline.systrace.FrescoSystrace;
import javax.annotation.Nullable;

/** Uses ExecutorService to move further computation to different thread */
public class ThreadHandoffProducer<T> implements Producer<T> {

  public static final String PRODUCER_NAME = "BackgroundThreadHandoffProducer";

  private final Producer<T> mInputProducer;
  private final ThreadHandoffProducerQueue mThreadHandoffProducerQueue;

  public ThreadHandoffProducer(
      final Producer<T> inputProducer,
      final ThreadHandoffProducerQueue inputThreadHandoffProducerQueue) {
    mInputProducer = Preconditions.checkNotNull(inputProducer);
    mThreadHandoffProducerQueue = inputThreadHandoffProducerQueue;
  }

  @Override
  public void produceResults(final Consumer<T> consumer, final ProducerContext context) {
    try {
      if (FrescoSystrace.isTracing()) {
        FrescoSystrace.beginSection("ThreadHandoffProducer#produceResults");
      }
      final ProducerListener2 producerListener = context.getProducerListener();
      final StatefulProducerRunnable<T> statefulRunnable =
          new StatefulProducerRunnable<T>(consumer, producerListener, context, PRODUCER_NAME) {
            @Override
            protected void onSuccess(T ignored) {
              producerListener.onProducerFinishWithSuccess(context, PRODUCER_NAME, null);
              mInputProducer.produceResults(consumer, context);
            }

            @Override
            protected void disposeResult(T ignored) {}

            @Override
            protected @Nullable T getResult() throws Exception {
              return null;
            }
          };
      context.addCallbacks(
          new BaseProducerContextCallbacks() {
            @Override
            public void onCancellationRequested() {
              statefulRunnable.cancel();
              mThreadHandoffProducerQueue.remove(statefulRunnable);
            }
          });
      mThreadHandoffProducerQueue.addToQueueOrExecute(statefulRunnable);
    } finally {
      if (FrescoSystrace.isTracing()) {
        FrescoSystrace.endSection();
      }
    }
  }
}

@@ -280,16 +280,86 @@
 itions;%0A
+import com.facebook.imagepipeline.instrumentation.FrescoInstrumenter;%0A
 import c
@@ -2281,16 +2281,17 @@
     %7D);%0A
+%0A
       mT
@@ -2336,32 +2336,112 @@
 Execute(
-statefulRunnable
+%0A          FrescoInstrumenter.decorateRunnable(statefulRunnable, getInstrumentationTag(context))
 );%0A    %7D
@@ -2545,11 +2545,227 @@
    %7D%0A  %7D
+%0A%0A  @Nullable%0A  private static String getInstrumentationTag(ProducerContext context) %7B%0A    return FrescoInstrumenter.isTracing()%0A        ? %22ThreadHandoffProducer_produceResults_%22 + context.getId()%0A        : null;%0A  %7D
 %0A%7D%0A

Add Support for work instrumentation - ThreadHandoffProducer