CTS DownloadManagerTest testMinimumDownload failed

来源:互联网 发布:mac口红正红色色号 编辑:程序博客网 时间:2024/06/05 14:15

DownloadManagerTest testMinimumDownload代码如下:

    public void testMinimumDownload() throws Exception {        final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();        try {            IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);            mContext.registerReceiver(receiver, intentFilter);            long id = mDownloadManager.enqueue(new Request(getMinimumDownloadUrl()));            receiver.waitForDownloadComplete(LONG_TIMEOUT, id);            ParcelFileDescriptor fileDescriptor = mDownloadManager.openDownloadedFile(id);            assertEquals(MINIMUM_DOWNLOAD_BYTES, fileDescriptor.getStatSize());            Cursor cursor = null;            try {                cursor = mDownloadManager.query(new Query().setFilterById(id));                assertTrue(cursor.moveToNext());                assertEquals(DownloadManager.STATUS_SUCCESSFUL, cursor.getInt(                        cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)));                assertEquals(MINIMUM_DOWNLOAD_BYTES, cursor.getInt(                        cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)));                assertFalse(cursor.moveToNext());            } finally {                if (cursor != null) {                    cursor.close();                }            }            assertRemoveDownload(id, 0);        } finally {            mContext.unregisterReceiver(receiver);        }    }
函数一开始调用DownloadManager的openDownloadFile:

    public ParcelFileDescriptor openDownloadedFile(long id) throws FileNotFoundException {        return mResolver.openFileDescriptor(getDownloadUri(id), "r");    }
最终调用的是DownloadProvider的openFile:

    @Override    public ParcelFileDescriptor openFile(final Uri uri, String mode) throws FileNotFoundException {            ......
        } else {            try {                // When finished writing, update size and timestamp                return ParcelFileDescriptor.open(file, pfdMode, mHandler, new OnCloseListener() {                    @Override                    public void onClose(IOException e) {                        final ContentValues values = new ContentValues();                        values.put(Downloads.Impl.COLUMN_TOTAL_BYTES, file.length());                        values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION,                                System.currentTimeMillis());                        update(uri, values, null, null);                        if (shouldScan) {                            final Intent intent = new Intent(                                    Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);                            intent.setData(Uri.fromFile(file));                            getContext().sendBroadcast(intent);                        }                    }                });            } catch (IOException e) {                throw new FileNotFoundException("Failed to open for writing: " + e);            }        }      ......    }
这个方法返回ParcelFileDescriptor对象同时为其设置了一个OnCloseListener。

当下载完成之后会关闭这个ParcelFileDescriptor会调用这个OnCloseListener。然后后者会将ParcelFileDescriptor对应的文件大小信息更新到数据库中。

testMinimumDownload接着回去调用DownloadManager的enqueue,最终会导致DownloadProvider启动一个DownloadThread去下载对应的文件。

public class DownloadThread implements Runnable {    ......        @Override    public void run() {        ......       try {            ......            executeDownload();            ......      } catch(...) {            ......      } finally {            logDebug("Finished with status " + Downloads.Impl.statusToString(mInfoDelta.mStatus));            mNotifier.notifyDownloadSpeed(mId, 0);            finalizeDestination();            mInfoDelta.writeToDatabase();            if (Downloads.Impl.isStatusCompleted(mInfoDelta.mStatus)) {                mInfo.sendIntentIfRequested();            }            TrafficStats.clearThreadStatsTag();            TrafficStats.clearThreadStatsUid();            netPolicy.unregisterListener(mPolicyListener);            if (wakeLock != null) {                wakeLock.release();                wakeLock = null;            }      }        .....    }   ......}

这里下载完成后会通知DownloadProvider下载完成,进而导致前面的ParcelFileDescriptor对象被close导致OnCloseListener执行。

同时DownloadThread继续执行finalizeDestination方法:

private void finalizeDestination() {         ......        if (Downloads.Impl.isStatusError(mInfoDelta.mStatus)) {             ......        } else if (Downloads.Impl.isStatusSuccess(mInfoDelta.mStatus)) {            // When success, open access if local file            if (mInfoDelta.mFileName != null) {                try {                    // TODO: remove this once PackageInstaller works with content://                    Os.chmod(mInfoDelta.mFileName, 0644);                } catch (ErrnoException ignored) {                }                if (mInfo.mDestination != Downloads.Impl.DESTINATION_FILE_URI) {                    try {                        // Move into final resting place, if needed                        final File before = new File(mInfoDelta.mFileName);                        final File beforeDir = Helpers.getRunningDestinationDirectory(                                mContext, mInfo.mDestination);                        final File afterDir = Helpers.getSuccessDestinationDirectory(                                mContext, mInfo.mDestination);                        if (!beforeDir.equals(afterDir)                                && before.getParentFile().equals(beforeDir)) {                            final File after = new File(afterDir, before.getName());                            if (before.renameTo(after)) {                                mInfoDelta.mFileName = after.getAbsolutePath();                            }                        }                    } catch (IOException ignored) {                    }                }            }       }        ...... }

这里会重命名下载的文件。如果这个操作比OnCloseListener先被执行就导致,onCloseListener将数据库的下载文件大小信息跟新为0.

从而导致testMinimumDownload后续查询下载文件大小做assert操作失败。

0 0
原创粉丝点击