PageRenderTime 100ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/core/java/android/content/ContentProviderClient.java

https://gitlab.com/AvayKumar/android_frameworks_base
Java | 460 lines | 333 code | 40 blank | 87 comment | 39 complexity | f31a5ce66d7d8e2e8dfdae04ce65fd53 MD5 | raw file
  1. /*
  2. * Copyright (C) 2009 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.Cursor;
  19. import android.net.Uri;
  20. import android.os.Bundle;
  21. import android.os.CancellationSignal;
  22. import android.os.DeadObjectException;
  23. import android.os.Handler;
  24. import android.os.ICancellationSignal;
  25. import android.os.Looper;
  26. import android.os.ParcelFileDescriptor;
  27. import android.os.RemoteException;
  28. import android.util.Log;
  29. import com.android.internal.annotations.GuardedBy;
  30. import dalvik.system.CloseGuard;
  31. import java.io.FileNotFoundException;
  32. import java.util.ArrayList;
  33. /**
  34. * The public interface object used to interact with a {@link ContentProvider}. This is obtained by
  35. * calling {@link ContentResolver#acquireContentProviderClient}. This object must be released
  36. * using {@link #release} in order to indicate to the system that the {@link ContentProvider} is
  37. * no longer needed and can be killed to free up resources.
  38. *
  39. * <p>Note that you should generally create a new ContentProviderClient instance
  40. * for each thread that will be performing operations. Unlike
  41. * {@link ContentResolver}, the methods here such as {@link #query} and
  42. * {@link #openFile} are not thread safe -- you must not call
  43. * {@link #release()} on the ContentProviderClient those calls are made from
  44. * until you are finished with the data they have returned.
  45. */
  46. public class ContentProviderClient {
  47. private static final String TAG = "ContentProviderClient";
  48. @GuardedBy("ContentProviderClient.class")
  49. private static Handler sAnrHandler;
  50. private final ContentResolver mContentResolver;
  51. private final IContentProvider mContentProvider;
  52. private final String mPackageName;
  53. private final boolean mStable;
  54. private final CloseGuard mGuard = CloseGuard.get();
  55. private long mAnrTimeout;
  56. private NotRespondingRunnable mAnrRunnable;
  57. private boolean mReleased;
  58. /** {@hide} */
  59. ContentProviderClient(
  60. ContentResolver contentResolver, IContentProvider contentProvider, boolean stable) {
  61. mContentResolver = contentResolver;
  62. mContentProvider = contentProvider;
  63. mPackageName = contentResolver.mPackageName;
  64. mStable = stable;
  65. mGuard.open("release");
  66. }
  67. /** {@hide} */
  68. public void setDetectNotResponding(long timeoutMillis) {
  69. synchronized (ContentProviderClient.class) {
  70. mAnrTimeout = timeoutMillis;
  71. if (timeoutMillis > 0) {
  72. if (mAnrRunnable == null) {
  73. mAnrRunnable = new NotRespondingRunnable();
  74. }
  75. if (sAnrHandler == null) {
  76. sAnrHandler = new Handler(Looper.getMainLooper(), null, true /* async */);
  77. }
  78. } else {
  79. mAnrRunnable = null;
  80. }
  81. }
  82. }
  83. private void beforeRemote() {
  84. if (mAnrRunnable != null) {
  85. sAnrHandler.postDelayed(mAnrRunnable, mAnrTimeout);
  86. }
  87. }
  88. private void afterRemote() {
  89. if (mAnrRunnable != null) {
  90. sAnrHandler.removeCallbacks(mAnrRunnable);
  91. }
  92. }
  93. /** See {@link ContentProvider#query ContentProvider.query} */
  94. public Cursor query(Uri url, String[] projection, String selection,
  95. String[] selectionArgs, String sortOrder) throws RemoteException {
  96. return query(url, projection, selection, selectionArgs, sortOrder, null);
  97. }
  98. /** See {@link ContentProvider#query ContentProvider.query} */
  99. public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
  100. String sortOrder, CancellationSignal cancellationSignal) throws RemoteException {
  101. beforeRemote();
  102. try {
  103. ICancellationSignal remoteCancellationSignal = null;
  104. if (cancellationSignal != null) {
  105. cancellationSignal.throwIfCanceled();
  106. remoteCancellationSignal = mContentProvider.createCancellationSignal();
  107. cancellationSignal.setRemote(remoteCancellationSignal);
  108. }
  109. return mContentProvider.query(mPackageName, url, projection, selection, selectionArgs,
  110. sortOrder, remoteCancellationSignal);
  111. } catch (DeadObjectException e) {
  112. if (!mStable) {
  113. mContentResolver.unstableProviderDied(mContentProvider);
  114. }
  115. throw e;
  116. } finally {
  117. afterRemote();
  118. }
  119. }
  120. /** See {@link ContentProvider#getType ContentProvider.getType} */
  121. public String getType(Uri url) throws RemoteException {
  122. beforeRemote();
  123. try {
  124. return mContentProvider.getType(url);
  125. } catch (DeadObjectException e) {
  126. if (!mStable) {
  127. mContentResolver.unstableProviderDied(mContentProvider);
  128. }
  129. throw e;
  130. } finally {
  131. afterRemote();
  132. }
  133. }
  134. /** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
  135. public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
  136. beforeRemote();
  137. try {
  138. return mContentProvider.getStreamTypes(url, mimeTypeFilter);
  139. } catch (DeadObjectException e) {
  140. if (!mStable) {
  141. mContentResolver.unstableProviderDied(mContentProvider);
  142. }
  143. throw e;
  144. } finally {
  145. afterRemote();
  146. }
  147. }
  148. /** See {@link ContentProvider#canonicalize} */
  149. public final Uri canonicalize(Uri url) throws RemoteException {
  150. beforeRemote();
  151. try {
  152. return mContentProvider.canonicalize(mPackageName, url);
  153. } catch (DeadObjectException e) {
  154. if (!mStable) {
  155. mContentResolver.unstableProviderDied(mContentProvider);
  156. }
  157. throw e;
  158. } finally {
  159. afterRemote();
  160. }
  161. }
  162. /** See {@link ContentProvider#uncanonicalize} */
  163. public final Uri uncanonicalize(Uri url) throws RemoteException {
  164. beforeRemote();
  165. try {
  166. return mContentProvider.uncanonicalize(mPackageName, url);
  167. } catch (DeadObjectException e) {
  168. if (!mStable) {
  169. mContentResolver.unstableProviderDied(mContentProvider);
  170. }
  171. throw e;
  172. } finally {
  173. afterRemote();
  174. }
  175. }
  176. /** See {@link ContentProvider#insert ContentProvider.insert} */
  177. public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
  178. beforeRemote();
  179. try {
  180. return mContentProvider.insert(mPackageName, url, initialValues);
  181. } catch (DeadObjectException e) {
  182. if (!mStable) {
  183. mContentResolver.unstableProviderDied(mContentProvider);
  184. }
  185. throw e;
  186. } finally {
  187. afterRemote();
  188. }
  189. }
  190. /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
  191. public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
  192. beforeRemote();
  193. try {
  194. return mContentProvider.bulkInsert(mPackageName, url, initialValues);
  195. } catch (DeadObjectException e) {
  196. if (!mStable) {
  197. mContentResolver.unstableProviderDied(mContentProvider);
  198. }
  199. throw e;
  200. } finally {
  201. afterRemote();
  202. }
  203. }
  204. /** See {@link ContentProvider#delete ContentProvider.delete} */
  205. public int delete(Uri url, String selection, String[] selectionArgs)
  206. throws RemoteException {
  207. beforeRemote();
  208. try {
  209. return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
  210. } catch (DeadObjectException e) {
  211. if (!mStable) {
  212. mContentResolver.unstableProviderDied(mContentProvider);
  213. }
  214. throw e;
  215. } finally {
  216. afterRemote();
  217. }
  218. }
  219. /** See {@link ContentProvider#update ContentProvider.update} */
  220. public int update(Uri url, ContentValues values, String selection,
  221. String[] selectionArgs) throws RemoteException {
  222. beforeRemote();
  223. try {
  224. return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
  225. } catch (DeadObjectException e) {
  226. if (!mStable) {
  227. mContentResolver.unstableProviderDied(mContentProvider);
  228. }
  229. throw e;
  230. } finally {
  231. afterRemote();
  232. }
  233. }
  234. /**
  235. * See {@link ContentProvider#openFile ContentProvider.openFile}. Note that
  236. * this <em>does not</em>
  237. * take care of non-content: URIs such as file:. It is strongly recommended
  238. * you use the {@link ContentResolver#openFileDescriptor
  239. * ContentResolver.openFileDescriptor} API instead.
  240. */
  241. public ParcelFileDescriptor openFile(Uri url, String mode)
  242. throws RemoteException, FileNotFoundException {
  243. return openFile(url, mode, null);
  244. }
  245. /**
  246. * See {@link ContentProvider#openFile ContentProvider.openFile}. Note that
  247. * this <em>does not</em>
  248. * take care of non-content: URIs such as file:. It is strongly recommended
  249. * you use the {@link ContentResolver#openFileDescriptor
  250. * ContentResolver.openFileDescriptor} API instead.
  251. */
  252. public ParcelFileDescriptor openFile(Uri url, String mode, CancellationSignal signal)
  253. throws RemoteException, FileNotFoundException {
  254. beforeRemote();
  255. try {
  256. ICancellationSignal remoteSignal = null;
  257. if (signal != null) {
  258. signal.throwIfCanceled();
  259. remoteSignal = mContentProvider.createCancellationSignal();
  260. signal.setRemote(remoteSignal);
  261. }
  262. return mContentProvider.openFile(mPackageName, url, mode, remoteSignal, null);
  263. } catch (DeadObjectException e) {
  264. if (!mStable) {
  265. mContentResolver.unstableProviderDied(mContentProvider);
  266. }
  267. throw e;
  268. } finally {
  269. afterRemote();
  270. }
  271. }
  272. /**
  273. * See {@link ContentProvider#openAssetFile ContentProvider.openAssetFile}.
  274. * Note that this <em>does not</em>
  275. * take care of non-content: URIs such as file:. It is strongly recommended
  276. * you use the {@link ContentResolver#openAssetFileDescriptor
  277. * ContentResolver.openAssetFileDescriptor} API instead.
  278. */
  279. public AssetFileDescriptor openAssetFile(Uri url, String mode)
  280. throws RemoteException, FileNotFoundException {
  281. return openAssetFile(url, mode, null);
  282. }
  283. /**
  284. * See {@link ContentProvider#openAssetFile ContentProvider.openAssetFile}.
  285. * Note that this <em>does not</em>
  286. * take care of non-content: URIs such as file:. It is strongly recommended
  287. * you use the {@link ContentResolver#openAssetFileDescriptor
  288. * ContentResolver.openAssetFileDescriptor} API instead.
  289. */
  290. public AssetFileDescriptor openAssetFile(Uri url, String mode, CancellationSignal signal)
  291. throws RemoteException, FileNotFoundException {
  292. beforeRemote();
  293. try {
  294. ICancellationSignal remoteSignal = null;
  295. if (signal != null) {
  296. signal.throwIfCanceled();
  297. remoteSignal = mContentProvider.createCancellationSignal();
  298. signal.setRemote(remoteSignal);
  299. }
  300. return mContentProvider.openAssetFile(mPackageName, url, mode, remoteSignal);
  301. } catch (DeadObjectException e) {
  302. if (!mStable) {
  303. mContentResolver.unstableProviderDied(mContentProvider);
  304. }
  305. throw e;
  306. } finally {
  307. afterRemote();
  308. }
  309. }
  310. /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
  311. public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
  312. String mimeType, Bundle opts) throws RemoteException, FileNotFoundException {
  313. return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
  314. }
  315. /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
  316. public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
  317. String mimeType, Bundle opts, CancellationSignal signal)
  318. throws RemoteException, FileNotFoundException {
  319. beforeRemote();
  320. try {
  321. ICancellationSignal remoteSignal = null;
  322. if (signal != null) {
  323. signal.throwIfCanceled();
  324. remoteSignal = mContentProvider.createCancellationSignal();
  325. signal.setRemote(remoteSignal);
  326. }
  327. return mContentProvider.openTypedAssetFile(
  328. mPackageName, uri, mimeType, opts, remoteSignal);
  329. } catch (DeadObjectException e) {
  330. if (!mStable) {
  331. mContentResolver.unstableProviderDied(mContentProvider);
  332. }
  333. throw e;
  334. } finally {
  335. afterRemote();
  336. }
  337. }
  338. /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
  339. public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
  340. throws RemoteException, OperationApplicationException {
  341. beforeRemote();
  342. try {
  343. return mContentProvider.applyBatch(mPackageName, operations);
  344. } catch (DeadObjectException e) {
  345. if (!mStable) {
  346. mContentResolver.unstableProviderDied(mContentProvider);
  347. }
  348. throw e;
  349. } finally {
  350. afterRemote();
  351. }
  352. }
  353. /** See {@link ContentProvider#call(String, String, Bundle)} */
  354. public Bundle call(String method, String arg, Bundle extras) throws RemoteException {
  355. beforeRemote();
  356. try {
  357. return mContentProvider.call(mPackageName, method, arg, extras);
  358. } catch (DeadObjectException e) {
  359. if (!mStable) {
  360. mContentResolver.unstableProviderDied(mContentProvider);
  361. }
  362. throw e;
  363. } finally {
  364. afterRemote();
  365. }
  366. }
  367. /**
  368. * Call this to indicate to the system that the associated {@link ContentProvider} is no
  369. * longer needed by this {@link ContentProviderClient}.
  370. * @return true if this was release, false if it was already released
  371. */
  372. public boolean release() {
  373. synchronized (this) {
  374. if (mReleased) {
  375. throw new IllegalStateException("Already released");
  376. }
  377. mReleased = true;
  378. mGuard.close();
  379. if (mStable) {
  380. return mContentResolver.releaseProvider(mContentProvider);
  381. } else {
  382. return mContentResolver.releaseUnstableProvider(mContentProvider);
  383. }
  384. }
  385. }
  386. @Override
  387. protected void finalize() throws Throwable {
  388. if (mGuard != null) {
  389. mGuard.warnIfOpen();
  390. }
  391. }
  392. /**
  393. * Get a reference to the {@link ContentProvider} that is associated with this
  394. * client. If the {@link ContentProvider} is running in a different process then
  395. * null will be returned. This can be used if you know you are running in the same
  396. * process as a provider, and want to get direct access to its implementation details.
  397. *
  398. * @return If the associated {@link ContentProvider} is local, returns it.
  399. * Otherwise returns null.
  400. */
  401. public ContentProvider getLocalContentProvider() {
  402. return ContentProvider.coerceToLocalContentProvider(mContentProvider);
  403. }
  404. /** {@hide} */
  405. public static void releaseQuietly(ContentProviderClient client) {
  406. if (client != null) {
  407. try {
  408. client.release();
  409. } catch (Exception ignored) {
  410. }
  411. }
  412. }
  413. private class NotRespondingRunnable implements Runnable {
  414. @Override
  415. public void run() {
  416. Log.w(TAG, "Detected provider not responding: " + mContentProvider);
  417. mContentResolver.appNotRespondingViaProvider(mContentProvider);
  418. }
  419. }
  420. }