blob: 188a964dcd89b3a62fabc6f6749482a69b1e9cb1
1 | #define LOG_TAG "TvClient" |
2 | #include <utils/Log.h> |
3 | #include <utils/threads.h> |
4 | #include <signal.h> |
5 | #include <binder/IServiceManager.h> |
6 | #include <binder/IMemory.h> |
7 | |
8 | #include <include/TvClient.h> |
9 | #include <include/ITvService.h> |
10 | |
11 | // client singleton for tv service binder interface |
12 | Mutex TvClient::mLock; |
13 | sp<ITvService> TvClient::mTvService; |
14 | sp<TvClient::DeathNotifier> TvClient::mDeathNotifier; |
15 | |
16 | // establish binder interface to tv service |
17 | const sp<ITvService> &TvClient::getTvService() { |
18 | Mutex::Autolock _l(mLock); |
19 | if (mTvService.get() == 0) { |
20 | sp<IServiceManager> sm = defaultServiceManager(); |
21 | sp<IBinder> binder; |
22 | do { |
23 | binder = sm->getService(String16("aml.tvserver")); |
24 | if (binder != 0) |
25 | break; |
26 | ALOGW("TvService not published, waiting..."); |
27 | usleep(500000); // 0.5 s |
28 | } while (true); |
29 | if (mDeathNotifier == NULL) { |
30 | mDeathNotifier = new DeathNotifier(); |
31 | } |
32 | binder->linkToDeath(mDeathNotifier); |
33 | mTvService = interface_cast<ITvService>(binder); |
34 | } |
35 | ALOGE_IF(mTvService == 0, "no TvService!?"); |
36 | return mTvService; |
37 | } |
38 | |
39 | TvClient::TvClient() { |
40 | init(); |
41 | } |
42 | |
43 | // construct a tv client from an existing tv remote |
44 | sp<TvClient> TvClient::create(const sp<ITv> &tv) { |
45 | ALOGD("create"); |
46 | if (tv == 0) { |
47 | ALOGE("tv remote is a NULL pointer"); |
48 | return 0; |
49 | } |
50 | |
51 | sp<TvClient> c = new TvClient(); |
52 | if (tv->connect(c) == NO_ERROR) { |
53 | c->mStatus = NO_ERROR; |
54 | c->mTv = tv; |
55 | IInterface::asBinder(tv)->linkToDeath(c); |
56 | } |
57 | return c; |
58 | } |
59 | |
60 | void TvClient::init() { |
61 | mStatus = UNKNOWN_ERROR; |
62 | } |
63 | |
64 | TvClient::~TvClient() { |
65 | disconnect(); |
66 | } |
67 | |
68 | sp<TvClient> TvClient::connect() { |
69 | ALOGD("Tv::connect------------------------------------------"); |
70 | sp<TvClient> c = new TvClient(); |
71 | const sp<ITvService> &cs = getTvService(); |
72 | if (cs != 0) { |
73 | c->mTv = cs->connect(c); |
74 | } |
75 | if (c->mTv != 0) { |
76 | IInterface::asBinder(c->mTv)->linkToDeath(c); |
77 | c->mStatus = NO_ERROR; |
78 | } else { |
79 | c.clear(); |
80 | } |
81 | return c; |
82 | } |
83 | |
84 | void TvClient::disconnect() { |
85 | ALOGD("disconnect"); |
86 | if (mTv != 0) { |
87 | mTv->disconnect(); |
88 | IInterface::asBinder(mTv)->unlinkToDeath(this); |
89 | mTv = 0; |
90 | } |
91 | } |
92 | |
93 | status_t TvClient::reconnect() { |
94 | ALOGD("reconnect"); |
95 | sp <ITv> c = mTv; |
96 | if (c == 0) return NO_INIT; |
97 | return c->connect(this); |
98 | } |
99 | |
100 | sp<ITv> TvClient::remote() { |
101 | return mTv; |
102 | } |
103 | |
104 | status_t TvClient::lock() { |
105 | sp <ITv> c = mTv; |
106 | if (c == 0) return NO_INIT; |
107 | return c->lock(); |
108 | } |
109 | |
110 | status_t TvClient::unlock() { |
111 | sp <ITv> c = mTv; |
112 | if (c == 0) return NO_INIT; |
113 | return c->unlock(); |
114 | } |
115 | |
116 | status_t TvClient::processCmd(const Parcel &p, Parcel *r) { |
117 | sp <ITv> c = mTv; |
118 | if (c == 0) return NO_INIT; |
119 | return c->processCmd(p, r); |
120 | } |
121 | |
122 | status_t TvClient::createSubtitle(const sp<IMemory> &share_mem) { |
123 | sp <ITv> c = mTv; |
124 | if (c == 0) return NO_INIT; |
125 | return c->createSubtitle(share_mem); |
126 | } |
127 | |
128 | status_t TvClient::createVideoFrame(const sp<IMemory> &share_mem, int iSourceMode, int iCapVideoLayerOnly) { |
129 | sp <ITv> c = mTv; |
130 | if (c == 0) return NO_INIT; |
131 | return c->createVideoFrame(share_mem, iSourceMode, iCapVideoLayerOnly); |
132 | } |
133 | |
134 | void TvClient::setListener(const sp<TvListener> &listener) { |
135 | ALOGD("tv------------Tv::setListener"); |
136 | Mutex::Autolock _l(mLock); |
137 | mListener = listener; |
138 | } |
139 | |
140 | // callback from tv service |
141 | void TvClient::notifyCallback(int32_t msgType, const Parcel &p) { |
142 | int size = p.dataSize(); |
143 | int pos = p.dataPosition(); |
144 | p.setDataPosition(0); |
145 | sp<TvListener> listener; |
146 | { |
147 | Mutex::Autolock _l(mLock); |
148 | listener = mListener; |
149 | } |
150 | if (listener != NULL) { |
151 | listener->notify(msgType, p); |
152 | } |
153 | } |
154 | |
155 | void TvClient::binderDied(const wp<IBinder> &who) { |
156 | ALOGW("ITv died"); |
157 | //notifyCallback(1, 2, 0); |
158 | } |
159 | |
160 | void TvClient::DeathNotifier::binderDied(const wp<IBinder> &who) { |
161 | ALOGW("-----------------binderDied"); |
162 | Mutex::Autolock _l(TvClient::mLock); |
163 | TvClient::mTvService.clear(); |
164 | ALOGW("kill myself"); |
165 | kill(getpid(), SIGKILL); |
166 | ALOGW("----------------Tv server died!"); |
167 | } |
168 | |
169 |