157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project/*
257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project *
457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * you may not use this file except in compliance with the License.
657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * You may obtain a copy of the License at
757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project *
857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project *
1057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * See the License for the specific language governing permissions and
1457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * limitations under the License.
1557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */
1657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
1757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectpackage com.android.providers.downloads;
1857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
1914961f94d762e733a733e3268fca1074d8da5f8cSteve Howardimport android.app.DownloadManager;
203398db8f3b195959faa2a7cf09918f364432ac28Steve Howardimport android.content.ContentResolver;
21071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.content.ContentUris;
22071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.content.ContentValues;
2357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.Context;
2457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.Intent;
255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howardimport android.database.Cursor;
26071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.net.ConnectivityManager;
27961024389b3782936a40a7d090d670290bb66c3cJeff Sharkeyimport android.net.NetworkInfo;
28961024389b3782936a40a7d090d670290bb66c3cJeff Sharkeyimport android.net.NetworkInfo.DetailedState;
29c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queruimport android.net.Uri;
30789745f667c65661d82ccbd5ef49fdb132911736Vasu Noriimport android.os.Environment;
3157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.provider.Downloads;
32071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.provider.Downloads.Impl;
33e00c31208405bd2e4c88e069df7a2b15237f70bfVasu Noriimport android.text.TextUtils;
34071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howardimport android.util.Log;
35ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howardimport android.util.Pair;
3657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
376da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
386da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
39ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howardimport java.util.ArrayList;
40ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howardimport java.util.Collection;
415224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howardimport java.util.Collections;
42ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howardimport java.util.List;
435224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard
4457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project/**
4557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Stores information about an individual download.
4657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */
4757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectpublic class DownloadInfo {
483398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    public static class Reader {
493398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        private ContentResolver mResolver;
503398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        private Cursor mCursor;
513398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
523398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        public Reader(ContentResolver resolver, Cursor cursor) {
533398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            mResolver = resolver;
543398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            mCursor = cursor;
553398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
563398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
573398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        public DownloadInfo newDownloadInfo(Context context, SystemFacade systemFacade) {
583398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            DownloadInfo info = new DownloadInfo(context, systemFacade);
593398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            updateFromDatabase(info);
603398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            readRequestHeaders(info);
613398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return info;
623398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
633398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
643398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        public void updateFromDatabase(DownloadInfo info) {
653398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mId = getLong(Downloads.Impl._ID);
661dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mUri = getString(Downloads.Impl.COLUMN_URI);
673398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mNoIntegrity = getInt(Downloads.Impl.COLUMN_NO_INTEGRITY) == 1;
681dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mHint = getString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
691dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mFileName = getString(Downloads.Impl._DATA);
701dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mMimeType = getString(Downloads.Impl.COLUMN_MIME_TYPE);
713398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mDestination = getInt(Downloads.Impl.COLUMN_DESTINATION);
723398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mVisibility = getInt(Downloads.Impl.COLUMN_VISIBILITY);
733398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mStatus = getInt(Downloads.Impl.COLUMN_STATUS);
743398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mNumFailed = getInt(Constants.FAILED_CONNECTIONS);
753398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            int retryRedirect = getInt(Constants.RETRY_AFTER_X_REDIRECT_COUNT);
763398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mRetryAfter = retryRedirect & 0xfffffff;
773398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mLastMod = getLong(Downloads.Impl.COLUMN_LAST_MODIFICATION);
781dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mPackage = getString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);
791dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mClass = getString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS);
801dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mExtras = getString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS);
811dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mCookies = getString(Downloads.Impl.COLUMN_COOKIE_DATA);
821dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mUserAgent = getString(Downloads.Impl.COLUMN_USER_AGENT);
831dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mReferer = getString(Downloads.Impl.COLUMN_REFERER);
843398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mTotalBytes = getLong(Downloads.Impl.COLUMN_TOTAL_BYTES);
853398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mCurrentBytes = getLong(Downloads.Impl.COLUMN_CURRENT_BYTES);
861dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mETag = getString(Constants.ETAG);
87665f4105ea68a05d85dcd22cc9d823f45f7e6a37Jeff Sharkey            info.mUid = getInt(Constants.UID);
88b18ed519040c1ecd98f8cb139adcc315a3f4eedcVasu Nori            info.mMediaScanned = getInt(Constants.MEDIA_SCANNED);
89e00c31208405bd2e4c88e069df7a2b15237f70bfVasu Nori            info.mDeleted = getInt(Downloads.Impl.COLUMN_DELETED) == 1;
901dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mMediaProviderUri = getString(Downloads.Impl.COLUMN_MEDIAPROVIDER_URI);
913398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mIsPublicApi = getInt(Downloads.Impl.COLUMN_IS_PUBLIC_API) != 0;
923398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mAllowedNetworkTypes = getInt(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES);
933398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mAllowRoaming = getInt(Downloads.Impl.COLUMN_ALLOW_ROAMING) != 0;
94a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey            info.mAllowMetered = getInt(Downloads.Impl.COLUMN_ALLOW_METERED) != 0;
951dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mTitle = getString(Downloads.Impl.COLUMN_TITLE);
961dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            info.mDescription = getString(Downloads.Impl.COLUMN_DESCRIPTION);
97d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            info.mBypassRecommendedSizeLimit =
98d319729622da1893e895f2e35f41d01ecdca3705Steve Howard                    getInt(Downloads.Impl.COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT);
993398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
1003398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            synchronized (this) {
1013398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                info.mControl = getInt(Downloads.Impl.COLUMN_CONTROL);
1023398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            }
1033398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
1043398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
1053398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        private void readRequestHeaders(DownloadInfo info) {
1063398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            info.mRequestHeaders.clear();
1073398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            Uri headerUri = Uri.withAppendedPath(
1083398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                    info.getAllDownloadsUri(), Downloads.Impl.RequestHeaders.URI_SEGMENT);
1093398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            Cursor cursor = mResolver.query(headerUri, null, null, null, null);
1103398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            try {
1113398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                int headerIndex =
1123398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                        cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_HEADER);
1133398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                int valueIndex =
1143398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                        cursor.getColumnIndexOrThrow(Downloads.Impl.RequestHeaders.COLUMN_VALUE);
1153398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
116ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard                    addHeader(info, cursor.getString(headerIndex), cursor.getString(valueIndex));
1173398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                }
1183398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            } finally {
1193398db8f3b195959faa2a7cf09918f364432ac28Steve Howard                cursor.close();
1203398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            }
1213398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
1223398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            if (info.mCookies != null) {
123ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard                addHeader(info, "Cookie", info.mCookies);
1243398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            }
1253398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            if (info.mReferer != null) {
126ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard                addHeader(info, "Referer", info.mReferer);
1273398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            }
1283398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
1293398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
130ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard        private void addHeader(DownloadInfo info, String header, String value) {
131ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard            info.mRequestHeaders.add(Pair.create(header, value));
132ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard        }
133ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard
1341dc416983a4638a250b67b11564466088cfa41f6Vasu Nori        private String getString(String column) {
1353398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            int index = mCursor.getColumnIndexOrThrow(column);
1361dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            String s = mCursor.getString(index);
1371dc416983a4638a250b67b11564466088cfa41f6Vasu Nori            return (TextUtils.isEmpty(s)) ? null : s;
1383398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
1393398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
1403398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        private Integer getInt(String column) {
1413398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return mCursor.getInt(mCursor.getColumnIndexOrThrow(column));
1423398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
1433398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
1443398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        private Long getLong(String column) {
1453398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return mCursor.getLong(mCursor.getColumnIndexOrThrow(column));
1463398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
1473398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    }
1483398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
149d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    // the following NETWORK_* constants are used to indicates specfic reasons for disallowing a
150d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    // download from using a network, since specific causes can require special handling
151d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
152d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    /**
153d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * The network is usable for the given download.
154d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     */
155d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public static final int NETWORK_OK = 1;
156d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
157d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    /**
15826604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     * There is no network connectivity.
159d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     */
16026604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    public static final int NETWORK_NO_CONNECTION = 2;
161d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
162d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    /**
163d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * The download exceeds the maximum size for this network.
164d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     */
165d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public static final int NETWORK_UNUSABLE_DUE_TO_SIZE = 3;
166d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
167d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    /**
168d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * The download exceeds the recommended maximum size for this network, the user must confirm for
169d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * this download to proceed without WiFi.
170d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     */
171d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public static final int NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE = 4;
172d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
173d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    /**
17426604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     * The current connection is roaming, and the download can't proceed over a roaming connection.
17526604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     */
17626604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    public static final int NETWORK_CANNOT_USE_ROAMING = 5;
17726604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
17826604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    /**
17926604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     * The app requesting the download specific that it can't use the current network connection.
18026604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     */
18126604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    public static final int NETWORK_TYPE_DISALLOWED_BY_REQUESTOR = 6;
18226604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
18326604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    /**
184961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey     * Current network is blocked for requesting application.
185961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey     */
186961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey    public static final int NETWORK_BLOCKED = 7;
187961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey
188961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey    /**
189d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * For intents used to notify the user that a download exceeds a size threshold, if this extra
190d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * is true, WiFi is required for this download size; otherwise, it is only recommended.
191d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     */
192d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public static final String EXTRA_IS_WIFI_REQUIRED = "isWifiRequired";
193d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
194d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
1953398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    public long mId;
196c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mUri;
197c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public boolean mNoIntegrity;
198c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mHint;
199c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mFileName;
200c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mMimeType;
201c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mDestination;
202c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mVisibility;
203c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mControl;
204c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mStatus;
205c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mNumFailed;
206c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public int mRetryAfter;
207c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public long mLastMod;
208c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mPackage;
209c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mClass;
210c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mExtras;
211c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mCookies;
212c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mUserAgent;
213c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mReferer;
214b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public long mTotalBytes;
215b5629da794cb3c1ca1970d206343743b165b9644Steve Howard    public long mCurrentBytes;
216c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru    public String mETag;
217665f4105ea68a05d85dcd22cc9d823f45f7e6a37Jeff Sharkey    public int mUid;
218b18ed519040c1ecd98f8cb139adcc315a3f4eedcVasu Nori    public int mMediaScanned;
219e00c31208405bd2e4c88e069df7a2b15237f70bfVasu Nori    public boolean mDeleted;
220e00c31208405bd2e4c88e069df7a2b15237f70bfVasu Nori    public String mMediaProviderUri;
2210a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public boolean mIsPublicApi;
2220a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public int mAllowedNetworkTypes;
2230a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    public boolean mAllowRoaming;
224a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey    public boolean mAllowMetered;
22597d590d5a1f583acb7992d20851bdc6cd0454d12Steve Howard    public String mTitle;
22697d590d5a1f583acb7992d20851bdc6cd0454d12Steve Howard    public String mDescription;
227d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public int mBypassRecommendedSizeLimit;
22857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
2294a977a52c3eb3ac08b94b81aef72fb618be39f81Jean-Baptiste Queru    public int mFuzz;
2304a977a52c3eb3ac08b94b81aef72fb618be39f81Jean-Baptiste Queru
231ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard    private List<Pair<String, String>> mRequestHeaders = new ArrayList<Pair<String, String>>();
232071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    private SystemFacade mSystemFacade;
233071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    private Context mContext;
234071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard
2353398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    private DownloadInfo(Context context, SystemFacade systemFacade) {
236071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        mContext = context;
237071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        mSystemFacade = systemFacade;
2385224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard        mFuzz = Helpers.sRandom.nextInt(1001);
2395224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard    }
24057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
241ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard    public Collection<Pair<String, String>> getHeaders() {
242ebb555c0687061993dd6a22d15f6aab2437ee8c5Steve Howard        return Collections.unmodifiableList(mRequestHeaders);
24357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    }
24457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
2453d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    public void sendIntentIfRequested() {
2460a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        if (mPackage == null) {
2470a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            return;
2480a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        }
2490a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
2500a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        Intent intent;
2510a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        if (mIsPublicApi) {
2520a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
2530a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            intent.setPackage(mPackage);
2543398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, mId);
2550a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        } else { // legacy behavior
2560a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            if (mClass == null) {
2570a77c62a82503b38c484e0079648f0231dd85d53Steve Howard                return;
2580a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            }
2590a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            intent = new Intent(Downloads.Impl.ACTION_DOWNLOAD_COMPLETED);
260c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru            intent.setClassName(mPackage, mClass);
261c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru            if (mExtras != null) {
2627dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru                intent.putExtra(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, mExtras);
26357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            }
26457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            // We only send the content: URI, for security reasons. Otherwise, malicious
26557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            //     applications would have an easier time spoofing download results by
26657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            //     sending spoofed intents.
2673d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard            intent.setData(getMyDownloadsUri());
26857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        }
2690a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        mSystemFacade.sendBroadcast(intent);
27057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    }
27157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
27257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    /**
273b108a273b150e81bf26553b8851d6241bc711f98Steve Howard     * Returns the time when a download should be restarted.
27457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project     */
275b108a273b150e81bf26553b8851d6241bc711f98Steve Howard    public long restartTime(long now) {
276b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        if (mNumFailed == 0) {
277b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            return now;
278b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        }
279c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru        if (mRetryAfter > 0) {
280c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru            return mLastMod + mRetryAfter;
2811fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project        }
282c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queru        return mLastMod +
2831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project                Constants.RETRY_FIRST_DELAY *
2844a977a52c3eb3ac08b94b81aef72fb618be39f81Jean-Baptiste Queru                    (1000 + mFuzz) * (1 << (mNumFailed - 1));
28557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    }
28657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
28757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    /**
2881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project     * Returns whether this download (which the download manager hasn't seen yet)
2891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project     * should be started.
29057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project     */
291b108a273b150e81bf26553b8851d6241bc711f98Steve Howard    private boolean isReadyToStart(long now) {
2926baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori        if (DownloadHandler.getInstance().hasDownloadInQueue(mId)) {
293b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            // already running
294b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            return false;
295b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        }
2967dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru        if (mControl == Downloads.Impl.CONTROL_PAUSED) {
2971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project            // the download is paused, so it's not going to start
2981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project            return false;
2991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project        }
300b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        switch (mStatus) {
301b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case 0: // status hasn't been initialized yet, this is a new download
302b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case Downloads.Impl.STATUS_PENDING: // download is explicit marked as ready to start
303b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case Downloads.Impl.STATUS_RUNNING: // download interrupted (process killed etc) while
304b108a273b150e81bf26553b8851d6241bc711f98Steve Howard                                                // running, without a chance to update the database
30557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project                return true;
30657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
307b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case Downloads.Impl.STATUS_WAITING_FOR_NETWORK:
308b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case Downloads.Impl.STATUS_QUEUED_FOR_WIFI:
309d319729622da1893e895f2e35f41d01ecdca3705Steve Howard                return checkCanUseNetwork() == NETWORK_OK;
310b108a273b150e81bf26553b8851d6241bc711f98Steve Howard
311b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            case Downloads.Impl.STATUS_WAITING_TO_RETRY:
312b108a273b150e81bf26553b8851d6241bc711f98Steve Howard                // download was waiting for a delayed restart
313b108a273b150e81bf26553b8851d6241bc711f98Steve Howard                return restartTime(now) <= now;
314789745f667c65661d82ccbd5ef49fdb132911736Vasu Nori            case Downloads.Impl.STATUS_DEVICE_NOT_FOUND_ERROR:
315789745f667c65661d82ccbd5ef49fdb132911736Vasu Nori                // is the media mounted?
316789745f667c65661d82ccbd5ef49fdb132911736Vasu Nori                return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
317789745f667c65661d82ccbd5ef49fdb132911736Vasu Nori            case Downloads.Impl.STATUS_INSUFFICIENT_SPACE_ERROR:
318579be0d0d0de6af307ee94af07720a568ed2e7d1Hideki Hayami                // avoids repetition of retrying download
319579be0d0d0de6af307ee94af07720a568ed2e7d1Hideki Hayami                return false;
32057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        }
32157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        return false;
32257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    }
32357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project
32457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    /**
32557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project     * Returns whether this download has a visible notification after
32657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project     * completion.
32757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project     */
32857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    public boolean hasCompletionNotification() {
3297dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru        if (!Downloads.Impl.isStatusCompleted(mStatus)) {
33057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            return false;
33157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        }
3327dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru        if (mVisibility == Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
33357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project            return true;
33457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        }
33557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project        return false;
33657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project    }
3371fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project
3381fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project    /**
3391fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project     * Returns whether this download is allowed to use the network.
340d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * @return one of the NETWORK_* constants
3411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project     */
342d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    public int checkCanUseNetwork() {
343961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        final NetworkInfo info = mSystemFacade.getActiveNetworkInfo(mUid);
344b92aa3a88dd25a798bbedc860d9b29aef42bbb0fJeff Sharkey        if (info == null || !info.isConnected()) {
34526604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            return NETWORK_NO_CONNECTION;
346071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        }
347961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        if (DetailedState.BLOCKED.equals(info.getDetailedState())) {
348961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey            return NETWORK_BLOCKED;
349961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        }
3500a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        if (!isRoamingAllowed() && mSystemFacade.isNetworkRoaming()) {
35126604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            return NETWORK_CANNOT_USE_ROAMING;
352071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        }
353a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey        if (!mAllowMetered && mSystemFacade.isActiveNetworkMetered()) {
354a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey            return NETWORK_TYPE_DISALLOWED_BY_REQUESTOR;
355a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey        }
356961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey        return checkIsNetworkTypeAllowed(info.getType());
357071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    }
358071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard
3590a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    private boolean isRoamingAllowed() {
3600a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        if (mIsPublicApi) {
3610a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            return mAllowRoaming;
3620a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        } else { // legacy behavior
3630a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            return mDestination != Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING;
3640a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        }
3650a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
3660a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
3670a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    /**
36826604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     * @return a non-localized string appropriate for logging corresponding to one of the
36926604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     * NETWORK_* constants.
37026604ffc248081b8014ff7260536d18b43cb0de9Steve Howard     */
37126604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    public String getLogMessageForNetworkError(int networkError) {
37226604ffc248081b8014ff7260536d18b43cb0de9Steve Howard        switch (networkError) {
37326604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            case NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE:
37426604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "download size exceeds recommended limit for mobile network";
37526604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
37626604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            case NETWORK_UNUSABLE_DUE_TO_SIZE:
37726604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "download size exceeds limit for mobile network";
37826604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
37926604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            case NETWORK_NO_CONNECTION:
38026604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "no network connection available";
38126604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
38226604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            case NETWORK_CANNOT_USE_ROAMING:
38326604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "download cannot use the current network connection because it is roaming";
38426604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
38526604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            case NETWORK_TYPE_DISALLOWED_BY_REQUESTOR:
38626604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "download was requested to not use the current network type";
38726604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
388961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey            case NETWORK_BLOCKED:
389961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey                return "network is blocked for requesting application";
390961024389b3782936a40a7d090d670290bb66c3cJeff Sharkey
39126604ffc248081b8014ff7260536d18b43cb0de9Steve Howard            default:
39226604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return "unknown error with network connectivity";
39326604ffc248081b8014ff7260536d18b43cb0de9Steve Howard        }
39426604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    }
39526604ffc248081b8014ff7260536d18b43cb0de9Steve Howard
39626604ffc248081b8014ff7260536d18b43cb0de9Steve Howard    /**
3970a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     * Check if this download can proceed over the given network type.
3980a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     * @param networkType a constant from ConnectivityManager.TYPE_*.
399d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * @return one of the NETWORK_* constants
4000a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     */
401d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    private int checkIsNetworkTypeAllowed(int networkType) {
4020a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        if (mIsPublicApi) {
403f720bc684b1a8332eb4d5f8d25c5feaf7eb54433Jeff Sharkey            final int flag = translateNetworkTypeToApiFlag(networkType);
404f720bc684b1a8332eb4d5f8d25c5feaf7eb54433Jeff Sharkey            final boolean allowAllNetworkTypes = mAllowedNetworkTypes == ~0;
405f720bc684b1a8332eb4d5f8d25c5feaf7eb54433Jeff Sharkey            if (!allowAllNetworkTypes && (flag & mAllowedNetworkTypes) == 0) {
40626604ffc248081b8014ff7260536d18b43cb0de9Steve Howard                return NETWORK_TYPE_DISALLOWED_BY_REQUESTOR;
4070a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            }
4080a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        }
409d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        return checkSizeAllowedForNetwork(networkType);
4100a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
4110a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
4120a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    /**
4130a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     * Translate a ConnectivityManager.TYPE_* constant to the corresponding
4140a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     * DownloadManager.Request.NETWORK_* bit flag.
4150a77c62a82503b38c484e0079648f0231dd85d53Steve Howard     */
4160a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    private int translateNetworkTypeToApiFlag(int networkType) {
4170a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        switch (networkType) {
4180a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            case ConnectivityManager.TYPE_MOBILE:
4190a77c62a82503b38c484e0079648f0231dd85d53Steve Howard                return DownloadManager.Request.NETWORK_MOBILE;
4200a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
4210a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            case ConnectivityManager.TYPE_WIFI:
4220a77c62a82503b38c484e0079648f0231dd85d53Steve Howard                return DownloadManager.Request.NETWORK_WIFI;
4230a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
42461dc320aa883a2fcf68d44ef0bbe4cd7c51a7655HÃ¥kan            case ConnectivityManager.TYPE_BLUETOOTH:
42561dc320aa883a2fcf68d44ef0bbe4cd7c51a7655HÃ¥kan                return DownloadManager.Request.NETWORK_BLUETOOTH;
42661dc320aa883a2fcf68d44ef0bbe4cd7c51a7655HÃ¥kan
4270a77c62a82503b38c484e0079648f0231dd85d53Steve Howard            default:
4280a77c62a82503b38c484e0079648f0231dd85d53Steve Howard                return 0;
4290a77c62a82503b38c484e0079648f0231dd85d53Steve Howard        }
4300a77c62a82503b38c484e0079648f0231dd85d53Steve Howard    }
4310a77c62a82503b38c484e0079648f0231dd85d53Steve Howard
432071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    /**
433071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard     * Check if the download's size prohibits it from running over the current network.
434d319729622da1893e895f2e35f41d01ecdca3705Steve Howard     * @return one of the NETWORK_* constants
435071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard     */
436d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    private int checkSizeAllowedForNetwork(int networkType) {
437071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        if (mTotalBytes <= 0) {
438d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            return NETWORK_OK; // we don't know the size yet
439071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        }
440071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        if (networkType == ConnectivityManager.TYPE_WIFI) {
441d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            return NETWORK_OK; // anything goes over wifi
442071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        }
4430d4f9f105c3a31475a36e9a1edfa868c66ff455fSteve Howard        Long maxBytesOverMobile = mSystemFacade.getMaxBytesOverMobile();
444d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        if (maxBytesOverMobile != null && mTotalBytes > maxBytesOverMobile) {
445d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            return NETWORK_UNUSABLE_DUE_TO_SIZE;
446d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        }
447d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        if (mBypassRecommendedSizeLimit == 0) {
448d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            Long recommendedMaxBytesOverMobile = mSystemFacade.getRecommendedMaxBytesOverMobile();
449d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            if (recommendedMaxBytesOverMobile != null
450d319729622da1893e895f2e35f41d01ecdca3705Steve Howard                    && mTotalBytes > recommendedMaxBytesOverMobile) {
451d319729622da1893e895f2e35f41d01ecdca3705Steve Howard                return NETWORK_RECOMMENDED_UNUSABLE_DUE_TO_SIZE;
452d319729622da1893e895f2e35f41d01ecdca3705Steve Howard            }
453071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard        }
454d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        return NETWORK_OK;
455071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard    }
456071bd7acb3185f4f1e807855605c5e6018e9742fSteve Howard
4575218d33d57990c3e3549c58bd3f0ac244dfc3d59Vasu Nori    void startIfReady(long now, StorageManager storageManager) {
458b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        if (!isReadyToStart(now)) {
459b108a273b150e81bf26553b8851d6241bc711f98Steve Howard            return;
460b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        }
461b108a273b150e81bf26553b8851d6241bc711f98Steve Howard
4625180de23e77139dd6971dfd48269242e3e3562d9Steve Howard        if (Constants.LOGV) {
4635180de23e77139dd6971dfd48269242e3e3562d9Steve Howard            Log.v(Constants.TAG, "Service spawning thread to handle download " + mId);
4645180de23e77139dd6971dfd48269242e3e3562d9Steve Howard        }
4655180de23e77139dd6971dfd48269242e3e3562d9Steve Howard        if (mStatus != Impl.STATUS_RUNNING) {
4665180de23e77139dd6971dfd48269242e3e3562d9Steve Howard            mStatus = Impl.STATUS_RUNNING;
4675180de23e77139dd6971dfd48269242e3e3562d9Steve Howard            ContentValues values = new ContentValues();
4685180de23e77139dd6971dfd48269242e3e3562d9Steve Howard            values.put(Impl.COLUMN_STATUS, mStatus);
4693d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard            mContext.getContentResolver().update(getAllDownloadsUri(), values, null, null);
4701fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project        }
4716baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori        DownloadHandler.getInstance().enqueueDownload(this);
4721fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project    }
473adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard
474adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard    public boolean isOnCache() {
475adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard        return (mDestination == Downloads.Impl.DESTINATION_CACHE_PARTITION
4769aadb4b3f2b3c914166ebfae8851fbecaf536f4fVasu Nori                || mDestination == Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION
477adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard                || mDestination == Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING
478adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard                || mDestination == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE);
479adb6887d3270d180c94eaf90878d5b67d74a8f28Steve Howard    }
4803d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard
4813d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    public Uri getMyDownloadsUri() {
4823d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, mId);
4833d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    }
4843d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard
4853d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    public Uri getAllDownloadsUri() {
4863d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard        return ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, mId);
4873d55d829c03fe78ad8cdab119293efb6c6e49c64Steve Howard    }
4883398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
4896da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey    public void dump(IndentingPrintWriter pw) {
4906da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println("DownloadInfo:");
4916da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.increaseIndent();
4926da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
4936da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mId", mId);
4946da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mLastMod", mLastMod);
4956da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mPackage", mPackage);
4966da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mUid", mUid);
4976da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
4986da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
4996da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mUri", mUri);
5006da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5016da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5026da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mMimeType", mMimeType);
5036da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mCookies", (mCookies != null) ? "yes" : "no");
5046da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mReferer", (mReferer != null) ? "yes" : "no");
5056da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mUserAgent", mUserAgent);
5066da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5076da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5086da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mFileName", mFileName);
5096da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mDestination", mDestination);
5106da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5116da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5126da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mStatus", Downloads.Impl.statusToString(mStatus));
5136da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mCurrentBytes", mCurrentBytes);
5146da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mTotalBytes", mTotalBytes);
5156da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5166da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5176da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mNumFailed", mNumFailed);
5186da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mRetryAfter", mRetryAfter);
5196da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mETag", mETag);
5206da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mIsPublicApi", mIsPublicApi);
5216da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5226da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5236da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mAllowedNetworkTypes", mAllowedNetworkTypes);
5246da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.printPair("mAllowRoaming", mAllowRoaming);
525a7ae77fdae69bcc6d6609d4639fed5d96e55eeaaJeff Sharkey        pw.printPair("mAllowMetered", mAllowMetered);
5266da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.println();
5276da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey
5286da2d0a2e1d046cd39270a46c3c77f8234f4cfaaJeff Sharkey        pw.decreaseIndent();
5293398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    }
5303398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
5313398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    /**
5323398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * Returns the amount of time (as measured from the "now" parameter)
5333398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * at which a download will be active.
5343398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * 0 = immediately - service should stick around to handle this download.
5353398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * -1 = never - service can go away without ever waking up.
5363398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * positive value - service must wake up in the future, as specified in ms from "now"
5373398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     */
5383398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    long nextAction(long now) {
5393398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        if (Downloads.Impl.isStatusCompleted(mStatus)) {
5403398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return -1;
5413398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
542b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        if (mStatus != Downloads.Impl.STATUS_WAITING_TO_RETRY) {
5433398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return 0;
5443398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
545b108a273b150e81bf26553b8851d6241bc711f98Steve Howard        long when = restartTime(now);
5463398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        if (when <= now) {
5473398db8f3b195959faa2a7cf09918f364432ac28Steve Howard            return 0;
5483398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        }
5493398db8f3b195959faa2a7cf09918f364432ac28Steve Howard        return when - now;
5503398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    }
5513398db8f3b195959faa2a7cf09918f364432ac28Steve Howard
5523398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    /**
5533398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     * Returns whether a file should be scanned
5543398db8f3b195959faa2a7cf09918f364432ac28Steve Howard     */
5553398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    boolean shouldScanFile() {
556b18ed519040c1ecd98f8cb139adcc315a3f4eedcVasu Nori        return (mMediaScanned == 0)
557971525cbe68f83a4f05cfe942f774486702947a7Vasu Nori                && (mDestination == Downloads.Impl.DESTINATION_EXTERNAL ||
558b18ed519040c1ecd98f8cb139adcc315a3f4eedcVasu Nori                        mDestination == Downloads.Impl.DESTINATION_FILE_URI ||
559b18ed519040c1ecd98f8cb139adcc315a3f4eedcVasu Nori                        mDestination == Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD)
5600a17c2a28738d6ecb274def0e8e54f556d89f5f3Gloria Wang                && Downloads.Impl.isStatusSuccess(mStatus);
5613398db8f3b195959faa2a7cf09918f364432ac28Steve Howard    }
562d319729622da1893e895f2e35f41d01ecdca3705Steve Howard
563d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    void notifyPauseDueToSize(boolean isWifiRequired) {
564d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        Intent intent = new Intent(Intent.ACTION_VIEW);
565d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        intent.setData(getAllDownloadsUri());
566d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        intent.setClassName(SizeLimitActivity.class.getPackage().getName(),
567d319729622da1893e895f2e35f41d01ecdca3705Steve Howard                SizeLimitActivity.class.getName());
568d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
569d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        intent.putExtra(EXTRA_IS_WIFI_REQUIRED, isWifiRequired);
570d319729622da1893e895f2e35f41d01ecdca3705Steve Howard        mContext.startActivity(intent);
571d319729622da1893e895f2e35f41d01ecdca3705Steve Howard    }
5726baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori
5736baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori    void startDownloadThread() {
5746baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori        DownloadThread downloader = new DownloadThread(mContext, mSystemFacade, this,
5756baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori                StorageManager.getInstance(mContext));
5766baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori        mSystemFacade.startThread(downloader);
5776baceb7073ed7858d3424ccf774e5f6a946bec59Vasu Nori    }
5782fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey
5792fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey    /**
5802fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey     * Query and return status of requested download.
5812fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey     */
5822fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey    public static int queryDownloadStatus(ContentResolver resolver, long id) {
5832fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey        final Cursor cursor = resolver.query(
5842fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                ContentUris.withAppendedId(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI, id),
5852fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                new String[] { Downloads.Impl.COLUMN_STATUS }, null, null, null);
5862fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey        try {
5872fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey            if (cursor.moveToFirst()) {
5882fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                return cursor.getInt(0);
5892fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey            } else {
5902fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                // TODO: increase strictness of value returned for unknown
5912fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                // downloads; this is safe default for now.
5922fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey                return Downloads.Impl.STATUS_PENDING;
5932fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey            }
5942fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey        } finally {
5952fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey            cursor.close();
5962fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey        }
5972fa007ef678b2283d47d007aa3dc91af683cc52cJeff Sharkey    }
59857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project}
599