PageRenderTime 25ms CodeModel.GetById 27ms RepoModel.GetById 2ms app.codeStats 0ms

/core/java/android/content/ContentProviderNative.java

https://github.com/PapaDocta/android_frameworks_base
Java | 572 lines | 423 code | 116 blank | 33 comment | 39 complexity | c9cde0018332a23952d92655e7fa5d90 MD5 | raw file
  1. /*
  2. * Copyright (C) 2006 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. package android.content;
  17. import android.content.res.AssetFileDescriptor;
  18. import android.database.BulkCursorNative;
  19. import android.database.BulkCursorToCursorAdaptor;
  20. import android.database.Cursor;
  21. import android.database.CursorWindow;
  22. import android.database.DatabaseUtils;
  23. import android.database.IBulkCursor;
  24. import android.database.IContentObserver;
  25. import android.net.Uri;
  26. import android.os.Binder;
  27. import android.os.Bundle;
  28. import android.os.RemoteException;
  29. import android.os.IBinder;
  30. import android.os.Parcel;
  31. import android.os.ParcelFileDescriptor;
  32. import android.os.Parcelable;
  33. import java.io.FileNotFoundException;
  34. import java.util.ArrayList;
  35. /**
  36. * {@hide}
  37. */
  38. abstract public class ContentProviderNative extends Binder implements IContentProvider {
  39. private static final String TAG = "ContentProvider";
  40. public ContentProviderNative()
  41. {
  42. attachInterface(this, descriptor);
  43. }
  44. /**
  45. * Cast a Binder object into a content resolver interface, generating
  46. * a proxy if needed.
  47. */
  48. static public IContentProvider asInterface(IBinder obj)
  49. {
  50. if (obj == null) {
  51. return null;
  52. }
  53. IContentProvider in =
  54. (IContentProvider)obj.queryLocalInterface(descriptor);
  55. if (in != null) {
  56. return in;
  57. }
  58. return new ContentProviderProxy(obj);
  59. }
  60. @Override
  61. public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
  62. throws RemoteException {
  63. try {
  64. switch (code) {
  65. case QUERY_TRANSACTION:
  66. {
  67. data.enforceInterface(IContentProvider.descriptor);
  68. Uri url = Uri.CREATOR.createFromParcel(data);
  69. // String[] projection
  70. int num = data.readInt();
  71. String[] projection = null;
  72. if (num > 0) {
  73. projection = new String[num];
  74. for (int i = 0; i < num; i++) {
  75. projection[i] = data.readString();
  76. }
  77. }
  78. // String selection, String[] selectionArgs...
  79. String selection = data.readString();
  80. num = data.readInt();
  81. String[] selectionArgs = null;
  82. if (num > 0) {
  83. selectionArgs = new String[num];
  84. for (int i = 0; i < num; i++) {
  85. selectionArgs[i] = data.readString();
  86. }
  87. }
  88. String sortOrder = data.readString();
  89. IContentObserver observer = IContentObserver.Stub.
  90. asInterface(data.readStrongBinder());
  91. CursorWindow window = CursorWindow.CREATOR.createFromParcel(data);
  92. // Flag for whether caller wants the number of
  93. // rows in the cursor and the position of the
  94. // "_id" column index (or -1 if non-existent)
  95. // Only to be returned if binder != null.
  96. boolean wantsCursorMetadata = data.readInt() != 0;
  97. IBulkCursor bulkCursor = bulkQuery(url, projection, selection,
  98. selectionArgs, sortOrder, observer, window);
  99. reply.writeNoException();
  100. if (bulkCursor != null) {
  101. reply.writeStrongBinder(bulkCursor.asBinder());
  102. if (wantsCursorMetadata) {
  103. reply.writeInt(bulkCursor.count());
  104. reply.writeInt(BulkCursorToCursorAdaptor.findRowIdColumnIndex(
  105. bulkCursor.getColumnNames()));
  106. }
  107. } else {
  108. reply.writeStrongBinder(null);
  109. }
  110. return true;
  111. }
  112. case GET_TYPE_TRANSACTION:
  113. {
  114. data.enforceInterface(IContentProvider.descriptor);
  115. Uri url = Uri.CREATOR.createFromParcel(data);
  116. String type = getType(url);
  117. reply.writeNoException();
  118. reply.writeString(type);
  119. return true;
  120. }
  121. case INSERT_TRANSACTION:
  122. {
  123. data.enforceInterface(IContentProvider.descriptor);
  124. Uri url = Uri.CREATOR.createFromParcel(data);
  125. ContentValues values = ContentValues.CREATOR.createFromParcel(data);
  126. Uri out = insert(url, values);
  127. reply.writeNoException();
  128. Uri.writeToParcel(reply, out);
  129. return true;
  130. }
  131. case BULK_INSERT_TRANSACTION:
  132. {
  133. data.enforceInterface(IContentProvider.descriptor);
  134. Uri url = Uri.CREATOR.createFromParcel(data);
  135. ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
  136. int count = bulkInsert(url, values);
  137. reply.writeNoException();
  138. reply.writeInt(count);
  139. return true;
  140. }
  141. case APPLY_BATCH_TRANSACTION:
  142. {
  143. data.enforceInterface(IContentProvider.descriptor);
  144. final int numOperations = data.readInt();
  145. final ArrayList<ContentProviderOperation> operations =
  146. new ArrayList<ContentProviderOperation>(numOperations);
  147. for (int i = 0; i < numOperations; i++) {
  148. operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
  149. }
  150. final ContentProviderResult[] results = applyBatch(operations);
  151. reply.writeNoException();
  152. reply.writeTypedArray(results, 0);
  153. return true;
  154. }
  155. case DELETE_TRANSACTION:
  156. {
  157. data.enforceInterface(IContentProvider.descriptor);
  158. Uri url = Uri.CREATOR.createFromParcel(data);
  159. String selection = data.readString();
  160. String[] selectionArgs = data.readStringArray();
  161. int count = delete(url, selection, selectionArgs);
  162. reply.writeNoException();
  163. reply.writeInt(count);
  164. return true;
  165. }
  166. case UPDATE_TRANSACTION:
  167. {
  168. data.enforceInterface(IContentProvider.descriptor);
  169. Uri url = Uri.CREATOR.createFromParcel(data);
  170. ContentValues values = ContentValues.CREATOR.createFromParcel(data);
  171. String selection = data.readString();
  172. String[] selectionArgs = data.readStringArray();
  173. int count = update(url, values, selection, selectionArgs);
  174. reply.writeNoException();
  175. reply.writeInt(count);
  176. return true;
  177. }
  178. case OPEN_FILE_TRANSACTION:
  179. {
  180. data.enforceInterface(IContentProvider.descriptor);
  181. Uri url = Uri.CREATOR.createFromParcel(data);
  182. String mode = data.readString();
  183. ParcelFileDescriptor fd;
  184. fd = openFile(url, mode);
  185. reply.writeNoException();
  186. if (fd != null) {
  187. reply.writeInt(1);
  188. fd.writeToParcel(reply,
  189. Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  190. } else {
  191. reply.writeInt(0);
  192. }
  193. return true;
  194. }
  195. case OPEN_ASSET_FILE_TRANSACTION:
  196. {
  197. data.enforceInterface(IContentProvider.descriptor);
  198. Uri url = Uri.CREATOR.createFromParcel(data);
  199. String mode = data.readString();
  200. AssetFileDescriptor fd;
  201. fd = openAssetFile(url, mode);
  202. reply.writeNoException();
  203. if (fd != null) {
  204. reply.writeInt(1);
  205. fd.writeToParcel(reply,
  206. Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  207. } else {
  208. reply.writeInt(0);
  209. }
  210. return true;
  211. }
  212. case CALL_TRANSACTION:
  213. {
  214. data.enforceInterface(IContentProvider.descriptor);
  215. String method = data.readString();
  216. String stringArg = data.readString();
  217. Bundle args = data.readBundle();
  218. Bundle responseBundle = call(method, stringArg, args);
  219. reply.writeNoException();
  220. reply.writeBundle(responseBundle);
  221. return true;
  222. }
  223. }
  224. } catch (Exception e) {
  225. DatabaseUtils.writeExceptionToParcel(reply, e);
  226. return true;
  227. }
  228. return super.onTransact(code, data, reply, flags);
  229. }
  230. public IBinder asBinder()
  231. {
  232. return this;
  233. }
  234. }
  235. final class ContentProviderProxy implements IContentProvider
  236. {
  237. public ContentProviderProxy(IBinder remote)
  238. {
  239. mRemote = remote;
  240. }
  241. public IBinder asBinder()
  242. {
  243. return mRemote;
  244. }
  245. // Like bulkQuery() but sets up provided 'adaptor' if not null.
  246. private IBulkCursor bulkQueryInternal(
  247. Uri url, String[] projection,
  248. String selection, String[] selectionArgs, String sortOrder,
  249. IContentObserver observer, CursorWindow window,
  250. BulkCursorToCursorAdaptor adaptor) throws RemoteException {
  251. Parcel data = Parcel.obtain();
  252. Parcel reply = Parcel.obtain();
  253. data.writeInterfaceToken(IContentProvider.descriptor);
  254. url.writeToParcel(data, 0);
  255. int length = 0;
  256. if (projection != null) {
  257. length = projection.length;
  258. }
  259. data.writeInt(length);
  260. for (int i = 0; i < length; i++) {
  261. data.writeString(projection[i]);
  262. }
  263. data.writeString(selection);
  264. if (selectionArgs != null) {
  265. length = selectionArgs.length;
  266. } else {
  267. length = 0;
  268. }
  269. data.writeInt(length);
  270. for (int i = 0; i < length; i++) {
  271. data.writeString(selectionArgs[i]);
  272. }
  273. data.writeString(sortOrder);
  274. data.writeStrongBinder(observer.asBinder());
  275. window.writeToParcel(data, 0);
  276. // Flag for whether or not we want the number of rows in the
  277. // cursor and the position of the "_id" column index (or -1 if
  278. // non-existent). Only to be returned if binder != null.
  279. final boolean wantsCursorMetadata = (adaptor != null);
  280. data.writeInt(wantsCursorMetadata ? 1 : 0);
  281. mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
  282. DatabaseUtils.readExceptionFromParcel(reply);
  283. IBulkCursor bulkCursor = null;
  284. IBinder bulkCursorBinder = reply.readStrongBinder();
  285. if (bulkCursorBinder != null) {
  286. bulkCursor = BulkCursorNative.asInterface(bulkCursorBinder);
  287. if (wantsCursorMetadata) {
  288. int rowCount = reply.readInt();
  289. int idColumnPosition = reply.readInt();
  290. if (bulkCursor != null) {
  291. adaptor.set(bulkCursor, rowCount, idColumnPosition);
  292. }
  293. }
  294. }
  295. data.recycle();
  296. reply.recycle();
  297. return bulkCursor;
  298. }
  299. public IBulkCursor bulkQuery(Uri url, String[] projection,
  300. String selection, String[] selectionArgs, String sortOrder, IContentObserver observer,
  301. CursorWindow window) throws RemoteException {
  302. return bulkQueryInternal(
  303. url, projection, selection, selectionArgs, sortOrder,
  304. observer, window,
  305. null /* BulkCursorToCursorAdaptor */);
  306. }
  307. public Cursor query(Uri url, String[] projection, String selection,
  308. String[] selectionArgs, String sortOrder) throws RemoteException {
  309. //TODO make a pool of windows so we can reuse memory dealers
  310. CursorWindow window = new CursorWindow(false /* window will be used remotely */);
  311. BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
  312. IBulkCursor bulkCursor = bulkQueryInternal(
  313. url, projection, selection, selectionArgs, sortOrder,
  314. adaptor.getObserver(), window,
  315. adaptor);
  316. if (bulkCursor == null) {
  317. return null;
  318. }
  319. return adaptor;
  320. }
  321. public String getType(Uri url) throws RemoteException
  322. {
  323. Parcel data = Parcel.obtain();
  324. Parcel reply = Parcel.obtain();
  325. data.writeInterfaceToken(IContentProvider.descriptor);
  326. url.writeToParcel(data, 0);
  327. mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
  328. DatabaseUtils.readExceptionFromParcel(reply);
  329. String out = reply.readString();
  330. data.recycle();
  331. reply.recycle();
  332. return out;
  333. }
  334. public Uri insert(Uri url, ContentValues values) throws RemoteException
  335. {
  336. Parcel data = Parcel.obtain();
  337. Parcel reply = Parcel.obtain();
  338. data.writeInterfaceToken(IContentProvider.descriptor);
  339. url.writeToParcel(data, 0);
  340. values.writeToParcel(data, 0);
  341. mRemote.transact(IContentProvider.INSERT_TRANSACTION, data, reply, 0);
  342. DatabaseUtils.readExceptionFromParcel(reply);
  343. Uri out = Uri.CREATOR.createFromParcel(reply);
  344. data.recycle();
  345. reply.recycle();
  346. return out;
  347. }
  348. public int bulkInsert(Uri url, ContentValues[] values) throws RemoteException {
  349. Parcel data = Parcel.obtain();
  350. Parcel reply = Parcel.obtain();
  351. data.writeInterfaceToken(IContentProvider.descriptor);
  352. url.writeToParcel(data, 0);
  353. data.writeTypedArray(values, 0);
  354. mRemote.transact(IContentProvider.BULK_INSERT_TRANSACTION, data, reply, 0);
  355. DatabaseUtils.readExceptionFromParcel(reply);
  356. int count = reply.readInt();
  357. data.recycle();
  358. reply.recycle();
  359. return count;
  360. }
  361. public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
  362. throws RemoteException, OperationApplicationException {
  363. Parcel data = Parcel.obtain();
  364. Parcel reply = Parcel.obtain();
  365. data.writeInterfaceToken(IContentProvider.descriptor);
  366. data.writeInt(operations.size());
  367. for (ContentProviderOperation operation : operations) {
  368. operation.writeToParcel(data, 0);
  369. }
  370. mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
  371. DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
  372. final ContentProviderResult[] results =
  373. reply.createTypedArray(ContentProviderResult.CREATOR);
  374. data.recycle();
  375. reply.recycle();
  376. return results;
  377. }
  378. public int delete(Uri url, String selection, String[] selectionArgs)
  379. throws RemoteException {
  380. Parcel data = Parcel.obtain();
  381. Parcel reply = Parcel.obtain();
  382. data.writeInterfaceToken(IContentProvider.descriptor);
  383. url.writeToParcel(data, 0);
  384. data.writeString(selection);
  385. data.writeStringArray(selectionArgs);
  386. mRemote.transact(IContentProvider.DELETE_TRANSACTION, data, reply, 0);
  387. DatabaseUtils.readExceptionFromParcel(reply);
  388. int count = reply.readInt();
  389. data.recycle();
  390. reply.recycle();
  391. return count;
  392. }
  393. public int update(Uri url, ContentValues values, String selection,
  394. String[] selectionArgs) throws RemoteException {
  395. Parcel data = Parcel.obtain();
  396. Parcel reply = Parcel.obtain();
  397. data.writeInterfaceToken(IContentProvider.descriptor);
  398. url.writeToParcel(data, 0);
  399. values.writeToParcel(data, 0);
  400. data.writeString(selection);
  401. data.writeStringArray(selectionArgs);
  402. mRemote.transact(IContentProvider.UPDATE_TRANSACTION, data, reply, 0);
  403. DatabaseUtils.readExceptionFromParcel(reply);
  404. int count = reply.readInt();
  405. data.recycle();
  406. reply.recycle();
  407. return count;
  408. }
  409. public ParcelFileDescriptor openFile(Uri url, String mode)
  410. throws RemoteException, FileNotFoundException {
  411. Parcel data = Parcel.obtain();
  412. Parcel reply = Parcel.obtain();
  413. data.writeInterfaceToken(IContentProvider.descriptor);
  414. url.writeToParcel(data, 0);
  415. data.writeString(mode);
  416. mRemote.transact(IContentProvider.OPEN_FILE_TRANSACTION, data, reply, 0);
  417. DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
  418. int has = reply.readInt();
  419. ParcelFileDescriptor fd = has != 0 ? reply.readFileDescriptor() : null;
  420. data.recycle();
  421. reply.recycle();
  422. return fd;
  423. }
  424. public AssetFileDescriptor openAssetFile(Uri url, String mode)
  425. throws RemoteException, FileNotFoundException {
  426. Parcel data = Parcel.obtain();
  427. Parcel reply = Parcel.obtain();
  428. data.writeInterfaceToken(IContentProvider.descriptor);
  429. url.writeToParcel(data, 0);
  430. data.writeString(mode);
  431. mRemote.transact(IContentProvider.OPEN_ASSET_FILE_TRANSACTION, data, reply, 0);
  432. DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(reply);
  433. int has = reply.readInt();
  434. AssetFileDescriptor fd = has != 0
  435. ? AssetFileDescriptor.CREATOR.createFromParcel(reply) : null;
  436. data.recycle();
  437. reply.recycle();
  438. return fd;
  439. }
  440. public Bundle call(String method, String request, Bundle args)
  441. throws RemoteException {
  442. Parcel data = Parcel.obtain();
  443. Parcel reply = Parcel.obtain();
  444. data.writeInterfaceToken(IContentProvider.descriptor);
  445. data.writeString(method);
  446. data.writeString(request);
  447. data.writeBundle(args);
  448. mRemote.transact(IContentProvider.CALL_TRANSACTION, data, reply, 0);
  449. DatabaseUtils.readExceptionFromParcel(reply);
  450. Bundle bundle = reply.readBundle();
  451. data.recycle();
  452. reply.recycle();
  453. return bundle;
  454. }
  455. private IBinder mRemote;
  456. }