• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef OBOETESTER_TEST_ERROR_CALLBACK_H
18 #define OBOETESTER_TEST_ERROR_CALLBACK_H
19 
20 #include "common/OboeDebug.h"
21 #include "oboe/Oboe.h"
22 #include <thread>
23 
24 /**
25  * This code is an experiment to see if we can cause a crash from the ErrorCallback.
26  */
27 class TestErrorCallback {
28 public:
29 
30     oboe::Result open();
31     oboe::Result start();
32     oboe::Result stop();
33     oboe::Result close();
34 
35     int test();
36 
getCallbackMagic()37     int32_t getCallbackMagic() {
38         return mCallbackMagic.load();
39     }
40 
41 protected:
42 
43     std::atomic<int32_t> mCallbackMagic{0};
44 
45 private:
46 
cleanup()47     void cleanup() {
48         mDataCallback.reset();
49         mErrorCallback.reset();
50         mStream.reset();
51     }
52 
53     class MyDataCallback : public oboe::AudioStreamDataCallback {    public:
54 
55         oboe::DataCallbackResult onAudioReady(
56                 oboe::AudioStream *audioStream,
57                 void *audioData,
58                 int32_t numFrames) override;
59 
60     };
61 
62     class MyErrorCallback : public oboe::AudioStreamErrorCallback {
63     public:
64 
MyErrorCallback(TestErrorCallback * parent)65         MyErrorCallback(TestErrorCallback *parent): mParent(parent) {}
66 
~MyErrorCallback()67         virtual ~MyErrorCallback() {
68             // If the delete occurs before onErrorAfterClose() then this bad magic
69             // value will be seen by the Java test code, causing a failure.
70             // It is also possible that this code will just cause OboeTester to crash!
71             mMagic = 0xdeadbeef;
72             LOGE("%s() called", __func__);
73         }
74 
onErrorBeforeClose(oboe::AudioStream * oboeStream,oboe::Result error)75         void onErrorBeforeClose(oboe::AudioStream *oboeStream, oboe::Result error) override {
76             LOGE("%s() - error = %s, parent = %p",
77                  __func__, oboe::convertToText(error), &mParent);
78             // Trigger a crash by "deleting" this callback object while in use!
79             // Do not try this at home. We are just trying to reproduce the crash
80             // reported in #1603.
81             std::thread t([this]() {
82                     this->mParent->cleanup(); // Possibly delete stream and callback objects.
83                     LOGE("onErrorBeforeClose called cleanup!");
84                 });
85             t.detach();
86             // There is a race condition between the deleting thread and this thread.
87             // We do not want to add synchronization because the object is getting deleted
88             // and cannot be relied on.
89             // So we sleep here to give the deleting thread a chance to win the race.
90             usleep(10 * 1000);
91         }
92 
onErrorAfterClose(oboe::AudioStream * oboeStream,oboe::Result error)93         void onErrorAfterClose(oboe::AudioStream *oboeStream, oboe::Result error) override {
94             // The callback was probably deleted by now.
95             LOGE("%s() - error = %s, mMagic = 0x%08X",
96                  __func__, oboe::convertToText(error), mMagic.load());
97             mParent->mCallbackMagic = mMagic.load();
98         }
99 
100     private:
101         TestErrorCallback *mParent;
102         // This must match the value in TestErrorCallbackActivity.java
103         static constexpr int32_t kMagicGood = 0x600DCAFE;
104         std::atomic<int32_t> mMagic{kMagicGood};
105     };
106 
107     std::shared_ptr<oboe::AudioStream> mStream;
108     std::shared_ptr<MyDataCallback> mDataCallback;
109     std::shared_ptr<MyErrorCallback> mErrorCallback;
110 
111     static constexpr int kChannelCount = 2;
112 };
113 
114 #endif //OBOETESTER_TEST_ERROR_CALLBACK_H
115