1/*
2 * Copyright 2012, 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 WIFI_DISPLAY_SOURCE_H_
18
19#define WIFI_DISPLAY_SOURCE_H_
20
21#include "VideoFormats.h"
22
23#include <media/stagefright/foundation/AHandler.h>
24#include <media/stagefright/foundation/ANetworkSession.h>
25
26#include <netinet/in.h>
27
28#include <utils/String16.h>
29
30namespace android {
31
32struct AReplyToken;
33struct IHDCP;
34class IRemoteDisplayClient;
35struct ParsedMessage;
36
37// Represents the RTSP server acting as a wifi display source.
38// Manages incoming connections, sets up Playback sessions as necessary.
39struct WifiDisplaySource : public AHandler {
40    static const unsigned kWifiDisplayDefaultPort = 7236;
41
42    WifiDisplaySource(
43            const String16 &opPackageName,
44            const sp<ANetworkSession> &netSession,
45            const sp<IRemoteDisplayClient> &client,
46            const char *path = NULL);
47
48    status_t start(const char *iface);
49    status_t stop();
50
51    status_t pause();
52    status_t resume();
53
54protected:
55    virtual ~WifiDisplaySource();
56    virtual void onMessageReceived(const sp<AMessage> &msg);
57
58private:
59    struct PlaybackSession;
60    struct HDCPObserver;
61
62    enum State {
63        INITIALIZED,
64        AWAITING_CLIENT_CONNECTION,
65        AWAITING_CLIENT_SETUP,
66        AWAITING_CLIENT_PLAY,
67        ABOUT_TO_PLAY,
68        PLAYING,
69        PLAYING_TO_PAUSED,
70        PAUSED,
71        PAUSED_TO_PLAYING,
72        AWAITING_CLIENT_TEARDOWN,
73        STOPPING,
74        STOPPED,
75    };
76
77    enum {
78        kWhatStart,
79        kWhatRTSPNotify,
80        kWhatStop,
81        kWhatPause,
82        kWhatResume,
83        kWhatReapDeadClients,
84        kWhatPlaybackSessionNotify,
85        kWhatKeepAlive,
86        kWhatHDCPNotify,
87        kWhatFinishStop2,
88        kWhatTeardownTriggerTimedOut,
89    };
90
91    struct ResponseID {
92        int32_t mSessionID;
93        int32_t mCSeq;
94
95        bool operator<(const ResponseID &other) const {
96            return mSessionID < other.mSessionID
97                || (mSessionID == other.mSessionID
98                        && mCSeq < other.mCSeq);
99        }
100    };
101
102    typedef status_t (WifiDisplaySource::*HandleRTSPResponseFunc)(
103            int32_t sessionID, const sp<ParsedMessage> &msg);
104
105    static const int64_t kReaperIntervalUs = 1000000ll;
106
107    // We request that the dongle send us a "TEARDOWN" in order to
108    // perform an orderly shutdown. We're willing to wait up to 2 secs
109    // for this message to arrive, after that we'll force a disconnect
110    // instead.
111    static const int64_t kTeardownTriggerTimeouSecs = 2;
112
113    static const int64_t kPlaybackSessionTimeoutSecs = 30;
114
115    static const int64_t kPlaybackSessionTimeoutUs =
116        kPlaybackSessionTimeoutSecs * 1000000ll;
117
118    static const AString sUserAgent;
119
120    String16 mOpPackageName;
121
122    State mState;
123    VideoFormats mSupportedSourceVideoFormats;
124    sp<ANetworkSession> mNetSession;
125    sp<IRemoteDisplayClient> mClient;
126    AString mMediaPath;
127    struct in_addr mInterfaceAddr;
128    int32_t mSessionID;
129
130    sp<AReplyToken> mStopReplyID;
131
132    AString mWfdClientRtpPorts;
133    int32_t mChosenRTPPort;  // extracted from "wfd_client_rtp_ports"
134
135    bool mSinkSupportsVideo;
136    VideoFormats mSupportedSinkVideoFormats;
137
138    VideoFormats::ResolutionType mChosenVideoResolutionType;
139    size_t mChosenVideoResolutionIndex;
140    VideoFormats::ProfileType mChosenVideoProfile;
141    VideoFormats::LevelType mChosenVideoLevel;
142
143    bool mSinkSupportsAudio;
144
145    bool mUsingPCMAudio;
146    int32_t mClientSessionID;
147
148    struct ClientInfo {
149        AString mRemoteIP;
150        AString mLocalIP;
151        int32_t mLocalPort;
152        int32_t mPlaybackSessionID;
153        sp<PlaybackSession> mPlaybackSession;
154    };
155    ClientInfo mClientInfo;
156
157    bool mReaperPending;
158
159    int32_t mNextCSeq;
160
161    KeyedVector<ResponseID, HandleRTSPResponseFunc> mResponseHandlers;
162
163    // HDCP specific section >>>>
164    bool mUsingHDCP;
165    bool mIsHDCP2_0;
166    int32_t mHDCPPort;
167    sp<IHDCP> mHDCP;
168    sp<HDCPObserver> mHDCPObserver;
169
170    bool mHDCPInitializationComplete;
171    bool mSetupTriggerDeferred;
172
173    bool mPlaybackSessionEstablished;
174
175    status_t makeHDCP();
176    // <<<< HDCP specific section
177
178    status_t sendM1(int32_t sessionID);
179    status_t sendM3(int32_t sessionID);
180    status_t sendM4(int32_t sessionID);
181
182    enum TriggerType {
183        TRIGGER_SETUP,
184        TRIGGER_TEARDOWN,
185        TRIGGER_PAUSE,
186        TRIGGER_PLAY,
187    };
188
189    // M5
190    status_t sendTrigger(int32_t sessionID, TriggerType triggerType);
191
192    status_t sendM16(int32_t sessionID);
193
194    status_t onReceiveM1Response(
195            int32_t sessionID, const sp<ParsedMessage> &msg);
196
197    status_t onReceiveM3Response(
198            int32_t sessionID, const sp<ParsedMessage> &msg);
199
200    status_t onReceiveM4Response(
201            int32_t sessionID, const sp<ParsedMessage> &msg);
202
203    status_t onReceiveM5Response(
204            int32_t sessionID, const sp<ParsedMessage> &msg);
205
206    status_t onReceiveM16Response(
207            int32_t sessionID, const sp<ParsedMessage> &msg);
208
209    void registerResponseHandler(
210            int32_t sessionID, int32_t cseq, HandleRTSPResponseFunc func);
211
212    status_t onReceiveClientData(const sp<AMessage> &msg);
213
214    status_t onOptionsRequest(
215            int32_t sessionID,
216            int32_t cseq,
217            const sp<ParsedMessage> &data);
218
219    status_t onSetupRequest(
220            int32_t sessionID,
221            int32_t cseq,
222            const sp<ParsedMessage> &data);
223
224    status_t onPlayRequest(
225            int32_t sessionID,
226            int32_t cseq,
227            const sp<ParsedMessage> &data);
228
229    status_t onPauseRequest(
230            int32_t sessionID,
231            int32_t cseq,
232            const sp<ParsedMessage> &data);
233
234    status_t onTeardownRequest(
235            int32_t sessionID,
236            int32_t cseq,
237            const sp<ParsedMessage> &data);
238
239    status_t onGetParameterRequest(
240            int32_t sessionID,
241            int32_t cseq,
242            const sp<ParsedMessage> &data);
243
244    status_t onSetParameterRequest(
245            int32_t sessionID,
246            int32_t cseq,
247            const sp<ParsedMessage> &data);
248
249    void sendErrorResponse(
250            int32_t sessionID,
251            const char *errorDetail,
252            int32_t cseq);
253
254    static void AppendCommonResponse(
255            AString *response, int32_t cseq, int32_t playbackSessionID = -1ll);
256
257    void scheduleReaper();
258    void scheduleKeepAlive(int32_t sessionID);
259
260    int32_t makeUniquePlaybackSessionID() const;
261
262    sp<PlaybackSession> findPlaybackSession(
263            const sp<ParsedMessage> &data, int32_t *playbackSessionID) const;
264
265    void finishStop();
266    void disconnectClientAsync();
267    void disconnectClient2();
268    void finishStopAfterDisconnectingClient();
269    void finishStop2();
270
271    void finishPlay();
272
273    DISALLOW_EVIL_CONSTRUCTORS(WifiDisplaySource);
274};
275
276}  // namespace android
277
278#endif  // WIFI_DISPLAY_SOURCE_H_
279