blob: 76ea7bee79c62eedfebf756061ffab4d2d6e2d88 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/*
Ruben Brunkd1176ef2014-02-21 10:51:38 -08002 * Copyright (C) 2008 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 */
Mathias Agopian65ab4712010-07-14 17:59:35 -070016
17#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
18#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
19
Igor Murashkin634a5152013-02-20 17:15:11 -080020#include <utils/Vector.h>
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080021#include <binder/AppOpsManager.h>
Mathias Agopian5462fc92010-07-14 18:41:18 -070022#include <binder/BinderService.h>
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080023#include <binder/IAppOpsCallback.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070024#include <camera/ICameraService.h>
Iliyan Malchev8951a972011-04-14 16:55:59 -070025#include <hardware/camera.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070026
Igor Murashkinc073ba52013-02-26 14:32:34 -080027#include <camera/ICamera.h>
28#include <camera/ICameraClient.h>
29#include <camera/IProCameraUser.h>
30#include <camera/IProCameraCallbacks.h>
Eino-Ville Talvala7b82efe2013-07-25 17:12:35 -070031#include <camera/camera2/ICameraDeviceUser.h>
32#include <camera/camera2/ICameraDeviceCallbacks.h>
Ruben Brunkd1176ef2014-02-21 10:51:38 -080033#include <camera/VendorTagDescriptor.h>
Jianing Weicb0652e2014-03-12 18:29:36 -070034#include <camera/CaptureResult.h>
Igor Murashkinc073ba52013-02-26 14:32:34 -080035
Igor Murashkinbfc99152013-02-27 12:55:20 -080036#include <camera/ICameraServiceListener.h>
37
Mathias Agopian65ab4712010-07-14 17:59:35 -070038/* This needs to be increased if we can have more cameras */
39#define MAX_CAMERAS 2
40
41namespace android {
42
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070043extern volatile int32_t gLogLevel;
44
Mathias Agopian65ab4712010-07-14 17:59:35 -070045class MemoryHeapBase;
46class MediaPlayer;
47
Mathias Agopian5462fc92010-07-14 18:41:18 -070048class CameraService :
49 public BinderService<CameraService>,
Igor Murashkinecf17e82012-10-02 16:05:11 -070050 public BnCameraService,
Igor Murashkincba2c162013-03-20 15:56:31 -070051 public IBinder::DeathRecipient,
52 public camera_module_callbacks_t
Mathias Agopian65ab4712010-07-14 17:59:35 -070053{
Mathias Agopian5462fc92010-07-14 18:41:18 -070054 friend class BinderService<CameraService>;
Mathias Agopian65ab4712010-07-14 17:59:35 -070055public:
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070056 class Client;
Igor Murashkin634a5152013-02-20 17:15:11 -080057 class BasicClient;
58
59 // Implementation of BinderService<T>
Mathias Agopian5462fc92010-07-14 18:41:18 -070060 static char const* getServiceName() { return "media.camera"; }
Mathias Agopian65ab4712010-07-14 17:59:35 -070061
62 CameraService();
63 virtual ~CameraService();
64
Igor Murashkin634a5152013-02-20 17:15:11 -080065 /////////////////////////////////////////////////////////////////////
Igor Murashkincba2c162013-03-20 15:56:31 -070066 // HAL Callbacks
67 virtual void onDeviceStatusChanged(int cameraId,
68 int newStatus);
69
70 /////////////////////////////////////////////////////////////////////
Igor Murashkin634a5152013-02-20 17:15:11 -080071 // ICameraService
Mathias Agopian65ab4712010-07-14 17:59:35 -070072 virtual int32_t getNumberOfCameras();
73 virtual status_t getCameraInfo(int cameraId,
74 struct CameraInfo* cameraInfo);
Zhijun He2b59be82013-09-25 10:14:30 -070075 virtual status_t getCameraCharacteristics(int cameraId,
76 CameraMetadata* cameraInfo);
Ruben Brunkd1176ef2014-02-21 10:51:38 -080077 virtual status_t getCameraVendorTagDescriptor(/*out*/ sp<VendorTagDescriptor>& desc);
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -080078
Ruben Brunk0f61d8f2013-08-08 13:07:18 -070079 virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
80 const String16& clientPackageName, int clientUid,
81 /*out*/
82 sp<ICamera>& device);
83
84 virtual status_t connectPro(const sp<IProCameraCallbacks>& cameraCb,
85 int cameraId, const String16& clientPackageName, int clientUid,
86 /*out*/
87 sp<IProCameraUser>& device);
88
89 virtual status_t connectDevice(
Igor Murashkine7ee7632013-06-11 18:10:18 -070090 const sp<ICameraDeviceCallbacks>& cameraCb,
91 int cameraId,
92 const String16& clientPackageName,
Ruben Brunk0f61d8f2013-08-08 13:07:18 -070093 int clientUid,
94 /*out*/
95 sp<ICameraDeviceUser>& device);
Mathias Agopian65ab4712010-07-14 17:59:35 -070096
Igor Murashkinbfc99152013-02-27 12:55:20 -080097 virtual status_t addListener(const sp<ICameraServiceListener>& listener);
98 virtual status_t removeListener(
99 const sp<ICameraServiceListener>& listener);
100
Igor Murashkin634a5152013-02-20 17:15:11 -0800101 // Extra permissions checks
Mathias Agopian65ab4712010-07-14 17:59:35 -0700102 virtual status_t onTransact(uint32_t code, const Parcel& data,
103 Parcel* reply, uint32_t flags);
Igor Murashkin634a5152013-02-20 17:15:11 -0800104
105 virtual status_t dump(int fd, const Vector<String16>& args);
106
107 /////////////////////////////////////////////////////////////////////
108 // Client functionality
109 virtual void removeClientByRemote(const wp<IBinder>& remoteBinder);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700110
111 enum sound_kind {
112 SOUND_SHUTTER = 0,
113 SOUND_RECORDING = 1,
114 NUM_SOUNDS
115 };
116
117 void loadSound();
118 void playSound(sound_kind kind);
119 void releaseSound();
120
Igor Murashkin98e24722013-06-19 19:51:04 -0700121 /////////////////////////////////////////////////////////////////////
122 // CameraDeviceFactory functionality
123 int getDeviceVersion(int cameraId, int* facing = NULL);
124
Igor Murashkin634a5152013-02-20 17:15:11 -0800125
126 /////////////////////////////////////////////////////////////////////
127 // CameraClient functionality
128
129 // returns plain pointer of client. Note that mClientLock should be acquired to
130 // prevent the client from destruction. The result can be NULL.
Igor Murashkine7ee7632013-06-11 18:10:18 -0700131 virtual BasicClient* getClientByIdUnsafe(int cameraId);
Igor Murashkin634a5152013-02-20 17:15:11 -0800132 virtual Mutex* getClientLockById(int cameraId);
133
134 class BasicClient : public virtual RefBase {
135 public:
136 virtual status_t initialize(camera_module_t *module) = 0;
137
138 virtual void disconnect() = 0;
139
Igor Murashkine7ee7632013-06-11 18:10:18 -0700140 // because we can't virtually inherit IInterface, which breaks
141 // virtual inheritance
142 virtual sp<IBinder> asBinderWrapper() = 0;
143
Igor Murashkine6800ce2013-03-04 17:25:57 -0800144 // Return the remote callback binder object (e.g. IProCameraCallbacks)
Igor Murashkine7ee7632013-06-11 18:10:18 -0700145 sp<IBinder> getRemote() {
Igor Murashkin44cfcf02013-03-01 16:22:28 -0800146 return mRemoteBinder;
Igor Murashkin634a5152013-02-20 17:15:11 -0800147 }
148
Igor Murashkine7ee7632013-06-11 18:10:18 -0700149 virtual status_t dump(int fd, const Vector<String16>& args) = 0;
150
Igor Murashkin634a5152013-02-20 17:15:11 -0800151 protected:
152 BasicClient(const sp<CameraService>& cameraService,
153 const sp<IBinder>& remoteCallback,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800154 const String16& clientPackageName,
Igor Murashkin634a5152013-02-20 17:15:11 -0800155 int cameraId,
156 int cameraFacing,
157 int clientPid,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800158 uid_t clientUid,
Igor Murashkin634a5152013-02-20 17:15:11 -0800159 int servicePid);
160
161 virtual ~BasicClient();
162
163 // the instance is in the middle of destruction. When this is set,
164 // the instance should not be accessed from callback.
165 // CameraService's mClientLock should be acquired to access this.
166 // - subclasses should set this to true in their destructors.
167 bool mDestructionStarted;
168
169 // these are initialized in the constructor.
170 sp<CameraService> mCameraService; // immutable after constructor
171 int mCameraId; // immutable after constructor
172 int mCameraFacing; // immutable after constructor
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800173 const String16 mClientPackageName;
Igor Murashkin634a5152013-02-20 17:15:11 -0800174 pid_t mClientPid;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800175 uid_t mClientUid; // immutable after constructor
Igor Murashkin634a5152013-02-20 17:15:11 -0800176 pid_t mServicePid; // immutable after constructor
177
178 // - The app-side Binder interface to receive callbacks from us
Igor Murashkine7ee7632013-06-11 18:10:18 -0700179 sp<IBinder> mRemoteBinder; // immutable after constructor
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800180
181 // permissions management
182 status_t startCameraOps();
183 status_t finishCameraOps();
184
185 // Notify client about a fatal error
Jianing Weicb0652e2014-03-12 18:29:36 -0700186 virtual void notifyError(
187 ICameraDeviceCallbacks::CameraErrorCode errorCode,
188 const CaptureResultExtras& resultExtras) = 0;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800189 private:
190 AppOpsManager mAppOpsManager;
191
192 class OpsCallback : public BnAppOpsCallback {
193 public:
194 OpsCallback(wp<BasicClient> client);
195 virtual void opChanged(int32_t op, const String16& packageName);
196
197 private:
198 wp<BasicClient> mClient;
199
200 }; // class OpsCallback
201
202 sp<OpsCallback> mOpsCallback;
203 // Track whether startCameraOps was called successfully, to avoid
204 // finishing what we didn't start.
205 bool mOpsActive;
206
207 // IAppOpsCallback interface, indirected through opListener
208 virtual void opChanged(int32_t op, const String16& packageName);
209 }; // class BasicClient
Igor Murashkin634a5152013-02-20 17:15:11 -0800210
211 class Client : public BnCamera, public BasicClient
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700212 {
213 public:
Igor Murashkin44cfcf02013-03-01 16:22:28 -0800214 typedef ICameraClient TCamCallbacks;
215
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700216 // ICamera interface (see ICamera for details)
217 virtual void disconnect();
218 virtual status_t connect(const sp<ICameraClient>& client) = 0;
219 virtual status_t lock() = 0;
220 virtual status_t unlock() = 0;
Eino-Ville Talvala1ce7c342013-08-21 13:57:21 -0700221 virtual status_t setPreviewTarget(const sp<IGraphicBufferProducer>& bufferProducer)=0;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700222 virtual void setPreviewCallbackFlag(int flag) = 0;
Eino-Ville Talvala3ee35502013-04-02 15:45:11 -0700223 virtual status_t setPreviewCallbackTarget(
224 const sp<IGraphicBufferProducer>& callbackProducer) = 0;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700225 virtual status_t startPreview() = 0;
226 virtual void stopPreview() = 0;
227 virtual bool previewEnabled() = 0;
228 virtual status_t storeMetaDataInBuffers(bool enabled) = 0;
229 virtual status_t startRecording() = 0;
230 virtual void stopRecording() = 0;
231 virtual bool recordingEnabled() = 0;
232 virtual void releaseRecordingFrame(const sp<IMemory>& mem) = 0;
233 virtual status_t autoFocus() = 0;
234 virtual status_t cancelAutoFocus() = 0;
235 virtual status_t takePicture(int msgType) = 0;
236 virtual status_t setParameters(const String8& params) = 0;
237 virtual String8 getParameters() const = 0;
238 virtual status_t sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
239
240 // Interface used by CameraService
241 Client(const sp<CameraService>& cameraService,
242 const sp<ICameraClient>& cameraClient,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800243 const String16& clientPackageName,
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700244 int cameraId,
245 int cameraFacing,
Igor Murashkinecf17e82012-10-02 16:05:11 -0700246 int clientPid,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800247 uid_t clientUid,
Igor Murashkinecf17e82012-10-02 16:05:11 -0700248 int servicePid);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700249 ~Client();
250
251 // return our camera client
Igor Murashkin44cfcf02013-03-01 16:22:28 -0800252 const sp<ICameraClient>& getRemoteCallback() {
253 return mRemoteCallback;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700254 }
255
Igor Murashkine7ee7632013-06-11 18:10:18 -0700256 virtual sp<IBinder> asBinderWrapper() {
257 return asBinder();
258 }
259
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700260 protected:
261 static Mutex* getClientLockFromCookie(void* user);
262 // convert client from cookie. Client lock should be acquired before getting Client.
263 static Client* getClientFromCookie(void* user);
264
Jianing Weicb0652e2014-03-12 18:29:36 -0700265 virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
266 const CaptureResultExtras& resultExtras);
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800267
Igor Murashkin634a5152013-02-20 17:15:11 -0800268 // Initialized in constructor
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700269
Igor Murashkin634a5152013-02-20 17:15:11 -0800270 // - The app-side Binder interface to receive callbacks from us
Igor Murashkin44cfcf02013-03-01 16:22:28 -0800271 sp<ICameraClient> mRemoteCallback;
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800272
273 }; // class Client
Igor Murashkin634a5152013-02-20 17:15:11 -0800274
275 class ProClient : public BnProCameraUser, public BasicClient {
276 public:
Igor Murashkin44cfcf02013-03-01 16:22:28 -0800277 typedef IProCameraCallbacks TCamCallbacks;
278
Igor Murashkin634a5152013-02-20 17:15:11 -0800279 ProClient(const sp<CameraService>& cameraService,
280 const sp<IProCameraCallbacks>& remoteCallback,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800281 const String16& clientPackageName,
Igor Murashkin634a5152013-02-20 17:15:11 -0800282 int cameraId,
283 int cameraFacing,
284 int clientPid,
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800285 uid_t clientUid,
Igor Murashkin634a5152013-02-20 17:15:11 -0800286 int servicePid);
287
288 virtual ~ProClient();
289
290 const sp<IProCameraCallbacks>& getRemoteCallback() {
291 return mRemoteCallback;
292 }
293
Igor Murashkin634a5152013-02-20 17:15:11 -0800294 /***
295 IProCamera implementation
296 ***/
Igor Murashkine6800ce2013-03-04 17:25:57 -0800297 virtual status_t connect(const sp<IProCameraCallbacks>& callbacks)
298 = 0;
299 virtual status_t exclusiveTryLock() = 0;
300 virtual status_t exclusiveLock() = 0;
301 virtual status_t exclusiveUnlock() = 0;
Igor Murashkin634a5152013-02-20 17:15:11 -0800302
Igor Murashkine6800ce2013-03-04 17:25:57 -0800303 virtual bool hasExclusiveLock() = 0;
Igor Murashkin634a5152013-02-20 17:15:11 -0800304
305 // Note that the callee gets a copy of the metadata.
306 virtual int submitRequest(camera_metadata_t* metadata,
Igor Murashkine6800ce2013-03-04 17:25:57 -0800307 bool streaming = false) = 0;
308 virtual status_t cancelRequest(int requestId) = 0;
Igor Murashkin634a5152013-02-20 17:15:11 -0800309
Igor Murashkinbfc99152013-02-27 12:55:20 -0800310 // Callbacks from camera service
Igor Murashkine6800ce2013-03-04 17:25:57 -0800311 virtual void onExclusiveLockStolen() = 0;
Igor Murashkinbfc99152013-02-27 12:55:20 -0800312
Igor Murashkin634a5152013-02-20 17:15:11 -0800313 protected:
Jianing Weicb0652e2014-03-12 18:29:36 -0700314 virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
315 const CaptureResultExtras& resultExtras);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700316
Eino-Ville Talvalaceb388d2013-02-19 10:40:14 -0800317 sp<IProCameraCallbacks> mRemoteCallback;
318 }; // class ProClient
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700319
Mathias Agopian65ab4712010-07-14 17:59:35 -0700320private:
Igor Murashkin634a5152013-02-20 17:15:11 -0800321
322 // Delay-load the Camera HAL module
323 virtual void onFirstRef();
324
Igor Murashkine6800ce2013-03-04 17:25:57 -0800325 // Step 1. Check if we can connect, before we acquire the service lock.
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700326 status_t validateConnect(int cameraId,
Igor Murashkine6800ce2013-03-04 17:25:57 -0800327 /*inout*/
328 int& clientUid) const;
329
330 // Step 2. Check if we can connect, after we acquire the service lock.
331 bool canConnectUnsafe(int cameraId,
332 const String16& clientPackageName,
333 const sp<IBinder>& remoteCallback,
334 /*out*/
Igor Murashkine7ee7632013-06-11 18:10:18 -0700335 sp<BasicClient> &client);
Igor Murashkine6800ce2013-03-04 17:25:57 -0800336
337 // When connection is successful, initialize client and track its death
Ruben Brunk0f61d8f2013-08-08 13:07:18 -0700338 status_t connectFinishUnsafe(const sp<BasicClient>& client,
Igor Murashkine7ee7632013-06-11 18:10:18 -0700339 const sp<IBinder>& remoteCallback);
Igor Murashkine6800ce2013-03-04 17:25:57 -0800340
Igor Murashkin634a5152013-02-20 17:15:11 -0800341 virtual sp<BasicClient> getClientByRemote(const wp<IBinder>& cameraClient);
342
Mathias Agopian65ab4712010-07-14 17:59:35 -0700343 Mutex mServiceLock;
Igor Murashkine7ee7632013-06-11 18:10:18 -0700344 // either a Client or CameraDeviceClient
345 wp<BasicClient> mClient[MAX_CAMERAS]; // protected by mServiceLock
Keun young Parkd8973a72012-03-28 14:13:09 -0700346 Mutex mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
Mathias Agopian65ab4712010-07-14 17:59:35 -0700347 int mNumberOfCameras;
348
Igor Murashkin634a5152013-02-20 17:15:11 -0800349 typedef wp<ProClient> weak_pro_client_ptr;
350 Vector<weak_pro_client_ptr> mProClientList[MAX_CAMERAS];
351
Igor Murashkinecf17e82012-10-02 16:05:11 -0700352 // needs to be called with mServiceLock held
Igor Murashkine7ee7632013-06-11 18:10:18 -0700353 sp<BasicClient> findClientUnsafe(const wp<IBinder>& cameraClient, int& outIndex);
Igor Murashkin634a5152013-02-20 17:15:11 -0800354 sp<ProClient> findProClientUnsafe(
355 const wp<IBinder>& cameraCallbacksRemote);
Igor Murashkinecf17e82012-10-02 16:05:11 -0700356
Mathias Agopian65ab4712010-07-14 17:59:35 -0700357 // atomics to record whether the hardware is allocated to some client.
358 volatile int32_t mBusy[MAX_CAMERAS];
359 void setCameraBusy(int cameraId);
360 void setCameraFree(int cameraId);
361
362 // sounds
Chih-Chung Changff4f55c2011-10-17 19:03:12 +0800363 MediaPlayer* newMediaPlayer(const char *file);
364
Mathias Agopian65ab4712010-07-14 17:59:35 -0700365 Mutex mSoundLock;
366 sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];
367 int mSoundRef; // reference count (release all MediaPlayer when 0)
368
Iliyan Malchev8951a972011-04-14 16:55:59 -0700369 camera_module_t *mModule;
Igor Murashkinecf17e82012-10-02 16:05:11 -0700370
Igor Murashkinbfc99152013-02-27 12:55:20 -0800371 Vector<sp<ICameraServiceListener> >
372 mListenerList;
373
374 // guard only mStatusList and the broadcasting of ICameraServiceListener
Igor Murashkincba2c162013-03-20 15:56:31 -0700375 mutable Mutex mStatusMutex;
Igor Murashkinbfc99152013-02-27 12:55:20 -0800376 ICameraServiceListener::Status
377 mStatusList[MAX_CAMERAS];
378
Igor Murashkincba2c162013-03-20 15:56:31 -0700379 // Read the current status (locks mStatusMutex)
380 ICameraServiceListener::Status
381 getStatus(int cameraId) const;
382
Igor Murashkin93747b92013-05-01 15:42:20 -0700383 typedef Vector<ICameraServiceListener::Status> StatusVector;
Igor Murashkinbfc99152013-02-27 12:55:20 -0800384 // Broadcast the new status if it changed (locks the service mutex)
385 void updateStatus(
386 ICameraServiceListener::Status status,
Igor Murashkin93747b92013-05-01 15:42:20 -0700387 int32_t cameraId,
388 const StatusVector *rejectSourceStates = NULL);
Igor Murashkinbfc99152013-02-27 12:55:20 -0800389
Igor Murashkinecf17e82012-10-02 16:05:11 -0700390 // IBinder::DeathRecipient implementation
Igor Murashkinbfc99152013-02-27 12:55:20 -0800391 virtual void binderDied(const wp<IBinder> &who);
Igor Murashkin634a5152013-02-20 17:15:11 -0800392
393 // Helpers
Igor Murashkinbfc99152013-02-27 12:55:20 -0800394
395 bool isValidCameraId(int cameraId);
Ruben Brunkd1176ef2014-02-21 10:51:38 -0800396
397 bool setUpVendorTags();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700398};
399
400} // namespace android
401
402#endif