Add onTuneFailed when canceling tuning operation

Due to RadioTuner API documentation, onTuneFailed should be called
when a pending tuning operation is canceled. Therefore, a new
result value Canceled was added in broadcast radio HAL. The
onTuneFailed callback for pending tuning operations in default HAL
was implemented by adding whatIfCanceled function field in Task
struct in WorkerThread utils class.

Bug: 257337458
Test: atest RadioTunerTest#cancel_whenTune
Test: atest RadioTunerTest#cancel_whenSeek
Change-Id: I901ab2cc3561082e5f11a9f6c33db044fc9bc28b
diff --git a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Result.aidl b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Result.aidl
index 07edae8..3464412 100644
--- a/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Result.aidl
+++ b/broadcastradio/aidl/aidl_api/android.hardware.broadcastradio/current/android/hardware/broadcastradio/Result.aidl
@@ -40,5 +40,6 @@
   INVALID_STATE = 3,
   NOT_SUPPORTED = 4,
   TIMEOUT = 5,
-  UNKNOWN_ERROR = 6,
+  CANCELED = 6,
+  UNKNOWN_ERROR = 7,
 }
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/ITunerCallback.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/ITunerCallback.aidl
index 1f0221c..8de12c8 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/ITunerCallback.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/ITunerCallback.aidl
@@ -36,6 +36,7 @@
      * @param result {@link Result#TIMEOUT} in case that tune(), seek() or
      *               step() is not completed within
      *               @link IBroadcastRadio#TUNER_TIMEOUT_MS}
+     *               or {@link Result#CANCELED} if the command was canceled.
      * @param selector A ProgramSelector structure passed from tune() call;
      *                 empty for step() and seek().
      */
diff --git a/broadcastradio/aidl/android/hardware/broadcastradio/Result.aidl b/broadcastradio/aidl/android/hardware/broadcastradio/Result.aidl
index 9985ccb..3f7ddac 100644
--- a/broadcastradio/aidl/android/hardware/broadcastradio/Result.aidl
+++ b/broadcastradio/aidl/android/hardware/broadcastradio/Result.aidl
@@ -55,6 +55,12 @@
     TIMEOUT,
 
     /**
+     * Error used when a tune, seek, step or operation is canceled before
+     * being processed.
+     */
+    CANCELED,
+
+    /**
      * Error that does not follow into the error categories above.
      */
     UNKNOWN_ERROR,
diff --git a/broadcastradio/aidl/default/BroadcastRadio.cpp b/broadcastradio/aidl/default/BroadcastRadio.cpp
index 0209a0e..42e550e 100644
--- a/broadcastradio/aidl/default/BroadcastRadio.cpp
+++ b/broadcastradio/aidl/default/BroadcastRadio.cpp
@@ -238,7 +238,8 @@
         }
         callback->onCurrentProgramInfoChanged(programInfo);
     };
-    mThread->schedule(task, kTuneDelayTimeMs);
+    auto cancelTask = [program, callback]() { callback->onTuneFailed(Result::CANCELED, program); };
+    mThread->schedule(task, cancelTask, kTuneDelayTimeMs);
 
     return ScopedAStatus::ok();
 }
@@ -258,6 +259,7 @@
 
     const auto& list = mVirtualRadio.getProgramList();
     std::shared_ptr<ITunerCallback> callback = mCallback;
+    auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
     if (list.empty()) {
         mIsTuneCompleted = false;
         auto task = [callback]() {
@@ -265,7 +267,7 @@
 
             callback->onTuneFailed(Result::TIMEOUT, {});
         };
-        mThread->schedule(task, kSeekDelayTimeMs);
+        mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
 
         return ScopedAStatus::ok();
     }
@@ -298,7 +300,7 @@
         }
         callback->onCurrentProgramInfoChanged(programInfo);
     };
-    mThread->schedule(task, kSeekDelayTimeMs);
+    mThread->schedule(task, cancelTask, kSeekDelayTimeMs);
 
     return ScopedAStatus::ok();
 }
@@ -352,7 +354,8 @@
         }
         callback->onCurrentProgramInfoChanged(programInfo);
     };
-    mThread->schedule(task, kStepDelayTimeMs);
+    auto cancelTask = [callback]() { callback->onTuneFailed(Result::CANCELED, {}); };
+    mThread->schedule(task, cancelTask, kStepDelayTimeMs);
 
     return ScopedAStatus::ok();
 }