CTS DownloadManagerTest testMinimumDownload failed

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值