• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 #pragma once
18 
19 #include <android-base/thread_annotations.h>
20 #include <utils/Looper.h>
21 #include <wakeup_client.grpc.pb.h>
22 #include <condition_variable>
23 #include <mutex>
24 #include <queue>
25 #include <string>
26 #include <thread>
27 
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace remoteaccess {
32 
33 // A class to generate fake task for testing. Not required for real implementation. In real
34 // implementation, the task should come from remote task server. This class is thread-safe.
35 class FakeTaskGenerator final {
36   public:
37     GetRemoteTasksResponse generateTask();
38 
39   private:
40     // Simulates the client ID for each task.
41     std::atomic<int> mCurrentClientId = 0;
42     constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef};
43 };
44 
45 struct TaskInfo {
46     // This is unique per-task. Note that a task might be popped and put back into the task queue,
47     // it will have a new task ID but the same clientId in the task data.
48     int taskId;
49     int64_t timestampInMs;
50     GetRemoteTasksResponse taskData;
51 };
52 
53 struct TaskInfoComparator {
54     // We want the smallest timestamp and smallest task ID on top.
operatorTaskInfoComparator55     bool operator()(const TaskInfo& l, const TaskInfo& r) {
56         return l.timestampInMs > r.timestampInMs ||
57                (l.timestampInMs == r.timestampInMs && l.taskId > r.taskId);
58     }
59 };
60 
61 // forward-declaration.
62 class TaskQueue;
63 
64 class TaskTimeoutMessageHandler final : public android::MessageHandler {
65   public:
66     TaskTimeoutMessageHandler(TaskQueue* taskQueue);
67     void handleMessage(const android::Message& message) override;
68 
69   private:
70     TaskQueue* mTaskQueue;
71 };
72 
73 // TaskQueue is thread-safe.
74 class TaskQueue final {
75   public:
76     TaskQueue();
77     ~TaskQueue();
78 
79     void add(const GetRemoteTasksResponse& response);
80     std::optional<GetRemoteTasksResponse> maybePopOne();
81     void waitForTask();
82     void stopWait();
83     void handleTaskTimeout();
84     bool isEmpty();
85 
86   private:
87     std::thread mCheckTaskTimeoutThread;
88     std::mutex mLock;
89     std::priority_queue<TaskInfo, std::vector<TaskInfo>, TaskInfoComparator> mTasks
90             GUARDED_BY(mLock);
91     // A variable to notify mTasks is not empty.
92     std::condition_variable mTasksNotEmptyCv;
93     bool mStopped GUARDED_BY(mLock);
94     android::sp<Looper> mLooper;
95     android::sp<TaskTimeoutMessageHandler> mTaskTimeoutMessageHandler;
96     std::atomic<int> mTaskIdCounter = 0;
97 
98     void checkForTestTimeoutLoop();
99     void waitForTaskWithLock(std::unique_lock<std::mutex>& lock);
100 };
101 
102 class TestWakeupClientServiceImpl final : public WakeupClient::Service {
103   public:
104     TestWakeupClientServiceImpl();
105 
106     ~TestWakeupClientServiceImpl();
107 
108     grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
109                                 grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
110 
111     grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
112                                       const NotifyWakeupRequiredRequest* request,
113                                       NotifyWakeupRequiredResponse* response) override;
114 
115   private:
116     // This is a thread for communicating with remote wakeup server (via network) and receive tasks
117     // from it.
118     std::thread mThread;
119     // A variable to notify server is stopping.
120     std::condition_variable mServerStoppedCv;
121     // Whether wakeup AP is required for executing tasks.
122     std::atomic<bool> mWakeupRequired = true;
123     std::mutex mLock;
124     bool mServerStopped GUARDED_BY(mLock);
125 
126     // Thread-safe. For test impl only.
127     FakeTaskGenerator mFakeTaskGenerator;
128     // Thread-sfae.
129     TaskQueue mTaskQueue;
130 
131     void fakeTaskGenerateLoop();
132 
133     void wakeupApplicationProcessor();
134 };
135 
136 }  // namespace remoteaccess
137 }  // namespace automotive
138 }  // namespace hardware
139 }  // namespace android
140