Automated sync from github.com/tensorflow/tensorflow (#2395)

BUG=automated sync from upstream
NO_CHECK_TFLITE_FILES=automated sync from upstream
diff --git a/tensorflow/lite/core/c/common.cc b/tensorflow/lite/core/c/common.cc
index 5430fe2..fd7c415 100644
--- a/tensorflow/lite/core/c/common.cc
+++ b/tensorflow/lite/core/c/common.cc
@@ -384,44 +384,6 @@
 
 TfLiteDelegate TfLiteDelegateCreate() { return TfLiteDelegate{}; }
 
-// LINT.IfChange
-#ifndef TF_LITE_STATIC_MEMORY
-TfLiteOpaqueDelegate* TfLiteOpaqueDelegateCreate(
-    const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder) {
-  if (!opaque_delegate_builder) return nullptr;
-
-  TfLiteDelegate* result = new TfLiteDelegate{};
-  result->opaque_delegate_builder = new TfLiteOpaqueDelegateBuilder{};
-  *(result->opaque_delegate_builder) = *opaque_delegate_builder;
-
-  return reinterpret_cast<TfLiteOpaqueDelegate*>(result);
-}
-
-void TfLiteOpaqueDelegateDelete(TfLiteOpaqueDelegate* opaque_delegate) {
-  if (!opaque_delegate) return;
-
-  const TfLiteDelegate* tflite_delegate =
-      reinterpret_cast<const TfLiteDelegate*>(opaque_delegate);
-  delete tflite_delegate->opaque_delegate_builder;
-  delete tflite_delegate;
-}
-#endif  // TF_LITE_STATIC_MEMORY
-
-void* TfLiteOpaqueDelegateGetData(const TfLiteOpaqueDelegate* delegate) {
-  if (!delegate) return nullptr;
-
-  // The following cast is safe only because this code is part of the
-  // TF Lite runtime implementation.  Apps using TF Lite should not rely on
-  // 'TfLiteOpaqueDelegate' and 'TfLiteDelegate' being equivalent.
-  const auto* tflite_delegate =
-      reinterpret_cast<const TfLiteDelegate*>(delegate);
-
-  if (!tflite_delegate->opaque_delegate_builder) return tflite_delegate->data_;
-
-  return tflite_delegate->opaque_delegate_builder->data;
-}
-// LINT.ThenChange(Google-internal path)
-
 // Returns a tensor data allocation strategy.
 TfLiteAllocationStrategy TfLiteTensorGetAllocationStrategy(
     const TfLiteTensor* const t) {
diff --git a/tensorflow/lite/core/c/common.h b/tensorflow/lite/core/c/common.h
index b2ceecb..4e48901 100644
--- a/tensorflow/lite/core/c/common.h
+++ b/tensorflow/lite/core/c/common.h
@@ -1348,15 +1348,19 @@
 TfLiteDelegate TfLiteDelegateCreate(void);
 
 /// `TfLiteOpaqueDelegateBuilder` is used for constructing
-/// `TfLiteOpaqueDelegate`, see `TfLiteOpaqueDelegateCreate` below.  Note:
-/// This struct is not ABI stable.
+/// `TfLiteOpaqueDelegate`, see `TfLiteOpaqueDelegateCreate` in c_api_opaque.h.
+/// NOTE: This struct is not ABI stable.
 ///
 /// For forward source compatibility `TfLiteOpaqueDelegateBuilder` objects
 /// should be brace-initialized, so that all fields (including any that might be
 /// added in the future) get zero-initialized.  The purpose of each field is
 /// exactly the same as with `TfLiteDelegate`.
 ///
-/// WARNING: This is an experimental interface that is subject to change.
+/// NOTE: This type is part of the TensorFlow Lite Extension APIs.
+/// We reserve the right to make changes to this API in future releases,
+/// potentially including non-backwards-compatible changes, on a different
+/// schedule than for the other TensorFlow Lite APIs. See
+/// https://www.tensorflow.org/guide/versions#separate_version_number_for_tensorflow_lite_extension_apis.
 typedef struct TfLiteOpaqueDelegateBuilder {
   /// Data that delegate needs to identify itself. This data is owned by the
   /// delegate. The delegate is owned in the user code, so the delegate is
@@ -1393,41 +1397,23 @@
   int64_t flags;
 } TfLiteOpaqueDelegateBuilder;
 
-// LINT.IfChange
 #ifndef TF_LITE_STATIC_MEMORY
-/// Creates an opaque delegate and returns its address.  The opaque delegate
-/// will behave according to the provided `opaque_delegate_builder`.  The
-/// lifetime of the objects pointed to by any of the fields within the
-/// `opaque_delegate_builder` must outlive the returned
-/// `TfLiteOpaqueDelegate` and any `TfLiteInterpreter`,
-/// `TfLiteInterpreterOptions`, `tflite::Interpreter`, or
-/// `tflite::InterpreterBuilder` that the delegate is added to.  The returned
-/// address should be passed to `TfLiteOpaqueDelegateDelete` for deletion.  If
-/// `opaque_delegate_builder` is a null pointer, then a null pointer will be
-/// returned.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
 TfLiteOpaqueDelegate* TfLiteOpaqueDelegateCreate(
     const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder);
 
-/// Deletes the provided opaque `delegate`.  This function has no effect if the
-/// `delegate` is a null pointer.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
 void TfLiteOpaqueDelegateDelete(TfLiteOpaqueDelegate* delegate);
 #endif  // TF_LITE_STATIC_MEMORY
 
-/// Returns a pointer to the data associated with the provided opaque
-/// `delegate`.
-///
-/// A null pointer will be returned when:
-/// - The `delegate` is null.
-/// - The `data` field of the `TfLiteOpaqueDelegateBuilder` used to construct
-///   the `delegate` was null.
-/// - Or in case of any other error.
-/// - The `delegate` has been constructed via a `TfLiteOpaqueDelegateBuilder`,
-///   but the `data` field of the `TfLiteOpaqueDelegateBuilder` is null.
-///
-///  The data_ field of `delegate` will be returned if the
-///  `opaque_delegate_builder` field is null.
+// See c_api_opaque.h.
+// This declaration in common.h is only for backwards compatibility.
+// NOTE: This function is part of the TensorFlow Lite Extension APIs, see above.
 void* TfLiteOpaqueDelegateGetData(const TfLiteOpaqueDelegate* delegate);
-// LINT.ThenChange(Google-internal path)
 
 /// Returns a tensor data allocation strategy.
 TfLiteAllocationStrategy TfLiteTensorGetAllocationStrategy(
diff --git a/tensorflow/lite/kernels/internal/portable_tensor_utils.h b/tensorflow/lite/kernels/internal/portable_tensor_utils.h
index c28892c..03bfdc8 100644
--- a/tensorflow/lite/kernels/internal/portable_tensor_utils.h
+++ b/tensorflow/lite/kernels/internal/portable_tensor_utils.h
@@ -259,7 +259,7 @@
     const int8_t* __restrict__ matrix, const uint8_t* __restrict__ ledger,
     const int m_rows, const int m_cols, const int8_t* __restrict__ vectors,
     const float* __restrict__ scaling_factors, int n_batch,
-    float* __restrict__ result);
+    float* __restrict__ result, const float* per_channel_scale = nullptr);
 
 // Same as the above 8, 8, 8 integer matmul except for the presence of zero
 // point and non-accumulative.
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
index d386203..b519d81 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.cc
@@ -294,7 +294,8 @@
 void PortableSparseMatrixBatchVectorMultiplyAccumulate(
     const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
     const int m_cols, const int8_t* __restrict__ vectors,
-    const float* scaling_factors, int n_batch, float* __restrict__ result) {
+    const float* scaling_factors, int n_batch, float* __restrict__ result,
+    const float* per_channel_scale) {
   static const int kBlockSize = 16;
   TFLITE_DCHECK_EQ(  // NOLINT
       m_cols % kBlockSize, 0);
@@ -319,7 +320,11 @@
           dotprod += (*row_ptr++) * (*vector_block_ptr++);
         }  // for block
       }    // for num_nonzero_blocks
-      result[batch * m_rows + row] += dotprod * batch_scaling_factor;
+      float scaling_factor = batch_scaling_factor;
+      if (per_channel_scale) {
+        scaling_factor *= per_channel_scale[row];
+      }
+      result[batch * m_rows + row] += dotprod * scaling_factor;
     }  // for row
   }    // for batch
 }
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
index 0416db0..ab0185e 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils.h
@@ -129,10 +129,11 @@
 void SparseMatrixBatchVectorMultiplyAccumulate(
     const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
     const int m_cols, const int8_t* __restrict__ vectors,
-    const float* scaling_factors, int n_batch, float* __restrict__ result) {
+    const float* scaling_factors, int n_batch, float* __restrict__ result,
+    const float* per_channel_scale) {
   PortableSparseMatrixBatchVectorMultiplyAccumulate(
-      matrix, ledger, m_rows, m_cols, vectors, scaling_factors, n_batch,
-      result);
+      matrix, ledger, m_rows, m_cols, vectors, scaling_factors, n_batch, result,
+      per_channel_scale);
 }
 
 void MatrixBatchVectorMultiplyAccumulate(
diff --git a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
index 6c404d5..6a1f18e 100644
--- a/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
+++ b/tensorflow/lite/kernels/internal/reference/portable_tensor_utils_impl.h
@@ -99,7 +99,8 @@
 void PortableSparseMatrixBatchVectorMultiplyAccumulate(
     const int8_t* __restrict__ matrix, const uint8_t* ledger, const int m_rows,
     const int m_cols, const int8_t* __restrict__ vectors,
-    const float* scaling_factors, int n_batch, float* __restrict__ result);
+    const float* scaling_factors, int n_batch, float* __restrict__ result,
+    const float* per_channel_scale);
 
 // Dot product of two vectors.
 float PortableVectorVectorDotProduct(const float* vector1, const float* vector2,