summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/include/TimedEventQueue.h
blob: 3e84256596f567efc03333da9e106f85620efbb5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef TIMED_EVENT_QUEUE_H_

#define TIMED_EVENT_QUEUE_H_

#include <pthread.h>

#include <utils/List.h>
#include <utils/RefBase.h>
#include <utils/threads.h>
#include <powermanager/IPowerManager.h>

namespace android {

struct TimedEventQueue {

    typedef int32_t event_id;

    struct Event : public RefBase {
        Event()
            : mEventID(0) {
        }

        virtual ~Event() {}

        event_id eventID() {
            return mEventID;
        }

    protected:
        virtual void fire(TimedEventQueue *queue, int64_t now_us) = 0;

    private:
        friend class TimedEventQueue;

        event_id mEventID;

        void setEventID(event_id id) {
            mEventID = id;
        }

        Event(const Event &);
        Event &operator=(const Event &);
    };

    class PMDeathRecipient : public IBinder::DeathRecipient {
    public:
                    PMDeathRecipient(TimedEventQueue *queue) : mQueue(queue) {}
        virtual     ~PMDeathRecipient() {}

        // IBinder::DeathRecipient
        virtual     void        binderDied(const wp<IBinder>& who);

    private:
                    PMDeathRecipient(const PMDeathRecipient&);
                    PMDeathRecipient& operator = (const PMDeathRecipient&);

                    TimedEventQueue *mQueue;
    };

    TimedEventQueue();
    ~TimedEventQueue();

    // Start executing the event loop.
    void start();

    // Stop executing the event loop, if flush is false, any pending
    // events are discarded, otherwise the queue will stop (and this call
    // return) once all pending events have been handled.
    void stop(bool flush = false);

    // Posts an event to the front of the queue (after all events that
    // have previously been posted to the front but before timed events).
    event_id postEvent(const sp<Event> &event);

    event_id postEventToBack(const sp<Event> &event);

    // It is an error to post an event with a negative delay.
    event_id postEventWithDelay(const sp<Event> &event, int64_t delay_us);

    // If the event is to be posted at a time that has already passed,
    // it will fire as soon as possible.
    event_id postTimedEvent(const sp<Event> &event, int64_t realtime_us);

    // Returns true iff event is currently in the queue and has been
    // successfully cancelled. In this case the event will have been
    // removed from the queue and won't fire.
    bool cancelEvent(event_id id);

    // Cancel any pending event that satisfies the predicate.
    // If stopAfterFirstMatch is true, only cancels the first event
    // satisfying the predicate (if any).
    void cancelEvents(
            bool (*predicate)(void *cookie, const sp<Event> &event),
            void *cookie,
            bool stopAfterFirstMatch = false);

    static int64_t getRealTimeUs();

    void clearPowerManager();

private:
    struct QueueItem {
        sp<Event> event;
        int64_t realtime_us;
        bool has_wakelock;
    };

    struct StopEvent : public TimedEventQueue::Event {
        virtual void fire(TimedEventQueue *queue, int64_t now_us) {
            queue->mStopped = true;
        }
    };

    pthread_t mThread;
    List<QueueItem> mQueue;
    Mutex mLock;
    Condition mQueueNotEmptyCondition;
    Condition mQueueHeadChangedCondition;
    event_id mNextEventID;

    bool mRunning;
    bool mStopped;

    sp<IPowerManager>       mPowerManager;
    sp<IBinder>             mWakeLockToken;
    const sp<PMDeathRecipient> mDeathRecipient;
    uint32_t                mWakeLockCount;

    static void *ThreadWrapper(void *me);
    void threadEntry();

    sp<Event> removeEventFromQueue_l(event_id id, bool *wakeLocked);

    void acquireWakeLock_l();
    void releaseWakeLock_l(bool force = false);

    TimedEventQueue(const TimedEventQueue &);
    TimedEventQueue &operator=(const TimedEventQueue &);
};

}  // namespace android

#endif  // TIMED_EVENT_QUEUE_H_