private ArrayList<V> loadAllFromCursor(Cursor cursor) { int count = cursor.getCount(); ArrayList<V> list = new ArrayList<V>(count); if (cursor instanceof CrossProcessCursor) { CursorWindow window = ((CrossProcessCursor) cursor).getWindow(); if (window != null) { if (window.getNumRows() == count) { cursor = new FastCursor(window); } } } final long start = System.currentTimeMillis(); if (cursor.moveToFirst()) { do { list.add(loadCurrent(cursor)); } while (cursor.moveToNext()); } return list; }
/** * Unlock identityScope during cursor.moveToNext() when it is about to fill the window (needs a db connection): * We should not hold the lock while trying to acquire a db connection to avoid deadlocks. */ private CursorWindow moveToNextUnlocked(Cursor cursor) { identityScope.unlock(); try { if (cursor.moveToNext()) { return ((CrossProcessCursor) cursor).getWindow(); } else { return null; } } finally { identityScope.lock(); } }
@Override public void fillWindow(int position, CursorWindow window) { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor; crossProcessCursor.fillWindow(position, window); return; } DatabaseUtils.cursorFillWindow(mCursor, position, window); }
@Override public CursorWindow getWindow() { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor; return crossProcessCursor.getWindow(); } return null; }
@Override public boolean onMove(int oldPosition, int newPosition) { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor)mCursor; return crossProcessCursor.onMove(oldPosition, newPosition); } return true; }
/** Reads all available rows from the given cursor and returns a list of entities. */ protected List<T> loadAllFromCursor(Cursor cursor) { int count = cursor.getCount(); List<T> list = new ArrayList<T>(count); if (cursor instanceof CrossProcessCursor) { CursorWindow window = ((CrossProcessCursor) cursor).getWindow(); if (window != null) { // E.g. Roboelectric has no Window at this point if (window.getNumRows() == count) { cursor = new FastCursor(window); } else { DaoLog.w("Window vs. result size: " + window.getNumRows() + "/" + count); } } } if (cursor.moveToFirst()) { if (identityScope != null) { identityScope.lock(); identityScope.reserveRoom(count); } try { do { list.add(loadCurrent(cursor, 0, false)); } while (cursor.moveToNext()); } finally { if (identityScope != null) { identityScope.unlock(); } } } return list; }
@Override public void fillWindow(int position, CursorWindow window) { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor) mCursor; crossProcessCursor.fillWindow(position, window); return; } cursorFillWindow(mCursor, position, window); }
@Override public CursorWindow getWindow() { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor) mCursor; return crossProcessCursor.getWindow(); } return null; }
@Override public boolean onMove(int oldPosition, int newPosition) { if (mCursor instanceof CrossProcessCursor) { final CrossProcessCursor crossProcessCursor = (CrossProcessCursor) mCursor; return crossProcessCursor.onMove(oldPosition, newPosition); } return true; }
protected MonitoredCursor(CrossProcessCursor cursor, Semaphore semaphore) { this.cursor = cursor; this.semaphore = semaphore; }
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws Exception { semaphore.acquire(); Cursor cursor = null; try { cursor = delegate.query(uri, projection, selection, selectionArgs, sortOrder); } finally { if (cursor == null) { semaphore.release(); } } // Android content resolvers can only process CrossProcessCursor instances if (!(cursor instanceof CrossProcessCursor)) { Timber.w("Unsupported cursor, returning null: %s", cursor); semaphore.release(); return null; } MonitoredCursor wrapped = new MonitoredCursor((CrossProcessCursor) cursor, semaphore); // Use a weak reference not to actively prevent garbage collection final WeakReference<MonitoredCursor> weakReference = new WeakReference<MonitoredCursor>(wrapped); // Make sure the cursor is closed after 30 seconds scheduledPool.schedule(new Runnable() { @Override public void run() { MonitoredCursor monitored = weakReference.get(); if (monitored != null && !monitored.isClosed()) { Timber.w("Forcibly closing remotely exposed cursor"); try { monitored.close(); } catch (Exception e) { Timber.w(e, "Exception while forcibly closing cursor"); } } } }, 30, TimeUnit.SECONDS); return wrapped; }
/** Reads all available rows from the given cursor and returns a list of entities. */ protected List<T> loadAllFromCursor(Cursor cursor) { int count = cursor.getCount(); if (count == 0) { return new ArrayList<T>(); } List<T> list = new ArrayList<T>(count); CursorWindow window = null; boolean useFastCursor = false; if (cursor instanceof CrossProcessCursor) { window = ((CrossProcessCursor) cursor).getWindow(); if (window != null) { // E.g. Robolectric has no Window at this point if (window.getNumRows() == count) { cursor = new FastCursor(window); useFastCursor = true; } else { DaoLog.d("Window vs. result size: " + window.getNumRows() + "/" + count); } } } if (cursor.moveToFirst()) { if (identityScope != null) { identityScope.lock(); identityScope.reserveRoom(count); } try { if (!useFastCursor && window != null && identityScope != null) { loadAllUnlockOnWindowBounds(cursor, window, list); } else { do { list.add(loadCurrent(cursor, 0, false)); } while (cursor.moveToNext()); } } finally { if (identityScope != null) { identityScope.unlock(); } } } return list; }
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) throws Exception { mSemaphore.acquire(); Cursor cursor = null; try { cursor = mDelegate.query(uri, projection, selection, selectionArgs, sortOrder); } finally { if (cursor == null) { mSemaphore.release(); } } /* Android content resolvers can only process CrossProcessCursor instances */ if (!(cursor instanceof CrossProcessCursor)) { Log.w(K9.LOG_TAG, "Unsupported cursor, returning null: " + cursor); mSemaphore.release(); return null; } final MonitoredCursor wrapped = new MonitoredCursor((CrossProcessCursor) cursor, mSemaphore); /* use a weak reference not to actively prevent garbage collection */ final WeakReference<MonitoredCursor> weakReference = new WeakReference<MonitoredCursor>(wrapped); /* make sure the cursor is closed after 30 seconds */ mScheduledPool.schedule(new Runnable() { @Override public void run() { final MonitoredCursor monitored = weakReference.get(); if (monitored != null && !monitored.isClosed()) { Log.w(K9.LOG_TAG, "Forcibly closing remotely exposed cursor"); try { monitored.close(); } catch (Exception e) { Log.w(K9.LOG_TAG, "Exception while forcibly closing cursor", e); } } } }, 30, TimeUnit.SECONDS); return wrapped; }
public boolean onMove(int oldPosition, int newPosition) { return ((CrossProcessCursor)mDatabaseCursor).onMove(oldPosition, newPosition); }
public ReadOnlyCursorWrapper(Cursor cursor) { super(cursor); mCursor = (CrossProcessCursor) cursor; }
/** * @param cursor * Never <code>null</code>. * @param semaphore * The semaphore to release on close. Never * <code>null</code>. */ protected MonitoredCursor(final CrossProcessCursor cursor, final Semaphore semaphore) { this.mCursor = cursor; this.mSemaphore = semaphore; }