DownloadProvider.java revision 0d8d89105c00edbad95a268aaae65f2ff94ed5a1
157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project/* 257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Copyright (C) 2007 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 1957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.ContentProvider; 2057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.ContentValues; 2157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.Context; 2257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.Intent; 2357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.UriMatcher; 2491e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapuimport android.content.pm.ApplicationInfo; 2557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.content.pm.PackageManager; 2691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapuimport android.content.pm.PackageManager.NameNotFoundException; 271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CrossProcessCursor; 2857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.Cursor; 291fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CursorWindow; 301fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport android.database.CursorWrapper; 31c6f5aad265cfc36a64cd2bdb5adf3cc9736bbd80Jean-Baptiste Queruimport android.database.SQLException; 3257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase; 3357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteOpenHelper; 3457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.database.sqlite.SQLiteQueryBuilder; 3557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.net.Uri; 3657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.Binder; 3757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.ParcelFileDescriptor; 3857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.os.Process; 3957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.provider.Downloads; 4057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.util.Config; 4157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport android.util.Log; 4257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 435224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howardimport com.google.common.annotations.VisibleForTesting; 445224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport java.io.File; 4657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectimport java.io.FileNotFoundException; 471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Projectimport java.util.HashSet; 485224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howardimport java.util.Map; 491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 5057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 5157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project/** 5257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Allows application to interact with the download manager. 5357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 5457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Projectpublic final class DownloadProvider extends ContentProvider { 5557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 5657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** Database filename */ 5757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DB_NAME = "downloads.db"; 581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /** Current database version */ 590a77c62a82503b38c484e0079648f0231dd85d53Steve Howard private static final int DB_VERSION = 102; 6057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** Name of table in the database */ 6157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DB_TABLE = "downloads"; 6257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 6357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** MIME type for the entire download list */ 6457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DOWNLOAD_LIST_TYPE = "vnd.android.cursor.dir/download"; 6557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** MIME type for an individual download */ 6657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final String DOWNLOAD_TYPE = "vnd.android.cursor.item/download"; 6757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 6857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher used to recognize URIs sent by applications */ 6957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH); 7057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher constant for the URI of the entire download list */ 7157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final int DOWNLOADS = 1; 7257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** URI matcher constant for the URI of an individual download */ 7357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private static final int DOWNLOADS_ID = 2; 745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** URI matcher constant for the URI of a download's request headers */ 755224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private static final int REQUEST_HEADERS_URI = 3; 7657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project static { 7757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sURIMatcher.addURI("downloads", "download", DOWNLOADS); 7857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sURIMatcher.addURI("downloads", "download/#", DOWNLOADS_ID); 795224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard sURIMatcher.addURI("downloads", "download/#/" + Downloads.Impl.RequestHeaders.URI_SEGMENT, 805224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard REQUEST_HEADERS_URI); 8157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 8257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final String[] sAppReadableColumnsArray = new String[] { 847dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._ID, 857dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_APP_DATA, 867dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl._DATA, 877dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_MIME_TYPE, 887dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_VISIBILITY, 897dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_DESTINATION, 907dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CONTROL, 917dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_STATUS, 927dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_LAST_MODIFICATION, 937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, 947dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_NOTIFICATION_CLASS, 957dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TOTAL_BYTES, 967dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_CURRENT_BYTES, 977dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.COLUMN_TITLE, 980a77c62a82503b38c484e0079648f0231dd85d53Steve Howard Downloads.Impl.COLUMN_DESCRIPTION, 990d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard Downloads.Impl.COLUMN_URI, 1001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project }; 1011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 1021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static HashSet<String> sAppReadableColumnsSet; 1031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project static { 1041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet = new HashSet<String>(); 1051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < sAppReadableColumnsArray.length; ++i) { 1061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project sAppReadableColumnsSet.add(sAppReadableColumnsArray[i]); 1071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1081fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 1091fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 11057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** The database that lies underneath this content provider */ 11157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private SQLiteOpenHelper mOpenHelper = null; 11257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 11391e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu /** List of uids that can access the downloads */ 11491e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu private int mSystemUid = -1; 11591e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu private int mDefContainerUid = -1; 11691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu 1176d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard @VisibleForTesting 1186d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard SystemFacade mSystemFacade; 1196d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard 12057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 12157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates and updated database on demand when opening it. 12257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Helper class to create database the first time the provider is 12357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * initialized and upgrade it when a new version of the provider needs 12457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * an updated version of the database. 12557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 12657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project private final class DatabaseHelper extends SQLiteOpenHelper { 12757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public DatabaseHelper(final Context context) { 12857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project super(context, DB_NAME, null, DB_VERSION); 12957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 13057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 13157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 13257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Creates database the first time we try to open it. 13357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 13457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 13557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public void onCreate(final SQLiteDatabase db) { 13657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 13757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "populating new database"); 13857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 1395224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard onUpgrade(db, 0, DB_VERSION); 14057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 14157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 14257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 14357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates the database format when a content provider is used 14457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * with a database that was created with a different format. 1455224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * 1465224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Note: to support downgrades, creating a table should always drop it first if it already 1475224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * exists. 14857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 14957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 1501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void onUpgrade(final SQLiteDatabase db, int oldV, final int newV) { 1515224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (oldV == 31) { 1525224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // 31 and 100 are identical, just in different codelines. Upgrading from 31 is the 1535224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // same as upgrading from 100. 1545224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 100; 1555224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } else if (oldV < 100) { 1565224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // no logic to upgrade from these older version, just recreate the DB 1575224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.i(Constants.TAG, "Upgrading downloads database from version " + oldV 1585224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + " to version " + newV + ", which will destroy all old data"); 1595224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 99; 1605224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } else if (oldV > newV) { 1615224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // user must have downgraded software; we have no way to know how to downgrade the 1625224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard // DB, so just recreate it 1635224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.i(Constants.TAG, "Downgrading downloads database from version " + oldV 1645224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + " (current version is " + newV + "), destroying all old data"); 1655224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard oldV = 99; 1665224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1675224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1685224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (int version = oldV + 1; version <= newV; version++) { 1695224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard upgradeTo(db, version); 1705224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1715224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1735224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 1745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Upgrade database from (version - 1) to version. 1755224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 1765224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void upgradeTo(SQLiteDatabase db, int version) { 1775224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard switch (version) { 1785224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case 100: 1795224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard createDownloadsTable(db); 1805224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard break; 1815224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1825224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case 101: 1835224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard createHeadersTable(db); 1845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard break; 1855224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 1860a77c62a82503b38c484e0079648f0231dd85d53Steve Howard case 102: 1870a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_IS_PUBLIC_API, 1880a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1890a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOW_ROAMING, 1900a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1910a77c62a82503b38c484e0079648f0231dd85d53Steve Howard addColumn(db, DB_TABLE, Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, 1920a77c62a82503b38c484e0079648f0231dd85d53Steve Howard "INTEGER NOT NULL DEFAULT 0"); 1930a77c62a82503b38c484e0079648f0231dd85d53Steve Howard break; 1940a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 1955224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard default: 1965224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new IllegalStateException("Don't know how to upgrade to " + version); 1975224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1985224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 1995224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 2005224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 2010a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * Add a column to a table using ALTER TABLE. 2020a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param dbTable name of the table 2030a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param columnName name of the column to add 2040a77c62a82503b38c484e0079648f0231dd85d53Steve Howard * @param columnDefinition SQL for the column definition 2050a77c62a82503b38c484e0079648f0231dd85d53Steve Howard */ 2060a77c62a82503b38c484e0079648f0231dd85d53Steve Howard private void addColumn(SQLiteDatabase db, String dbTable, String columnName, 2070a77c62a82503b38c484e0079648f0231dd85d53Steve Howard String columnDefinition) { 2080a77c62a82503b38c484e0079648f0231dd85d53Steve Howard db.execSQL("ALTER TABLE " + dbTable + " ADD COLUMN " + columnName + " " 2090a77c62a82503b38c484e0079648f0231dd85d53Steve Howard + columnDefinition); 2100a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 2110a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 2120a77c62a82503b38c484e0079648f0231dd85d53Steve Howard /** 2135224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Creates the table that'll hold the download information. 2145224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 2155224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void createDownloadsTable(SQLiteDatabase db) { 2165224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard try { 2175224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE); 2185224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("CREATE TABLE " + DB_TABLE + "(" + 2195224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + 2205224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_URI + " TEXT, " + 2215224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.RETRY_AFTER_X_REDIRECT_COUNT + " INTEGER, " + 2225224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_APP_DATA + " TEXT, " + 2235224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NO_INTEGRITY + " BOOLEAN, " + 2245224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_FILE_NAME_HINT + " TEXT, " + 2255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.OTA_UPDATE + " BOOLEAN, " + 2265224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl._DATA + " TEXT, " + 2275224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_MIME_TYPE + " TEXT, " + 2285224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_DESTINATION + " INTEGER, " + 2295224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.NO_SYSTEM_FILES + " BOOLEAN, " + 2305224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_VISIBILITY + " INTEGER, " + 2315224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_CONTROL + " INTEGER, " + 2325224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_STATUS + " INTEGER, " + 2335224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.FAILED_CONNECTIONS + " INTEGER, " + 2345224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_LAST_MODIFICATION + " BIGINT, " + 2355224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + " TEXT, " + 2365224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_CLASS + " TEXT, " + 2375224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS + " TEXT, " + 2385224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_COOKIE_DATA + " TEXT, " + 2395224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_USER_AGENT + " TEXT, " + 2405224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_REFERER + " TEXT, " + 2415224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_TOTAL_BYTES + " INTEGER, " + 2425224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_CURRENT_BYTES + " INTEGER, " + 2435224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.ETAG + " TEXT, " + 2445224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.UID + " INTEGER, " + 2455224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_OTHER_UID + " INTEGER, " + 2465224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_TITLE + " TEXT, " + 2475224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.COLUMN_DESCRIPTION + " TEXT, " + 2485224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Constants.MEDIA_SCANNED + " BOOLEAN);"); 2495224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } catch (SQLException ex) { 2505224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Log.e(Constants.TAG, "couldn't create table in downloads database"); 2515224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw ex; 2525224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 2535224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 2545224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 2555224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void createHeadersTable(SQLiteDatabase db) { 2565224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("DROP TABLE IF EXISTS " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE); 2575224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.execSQL("CREATE TABLE " + Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE + "(" + 2585224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard "id INTEGER PRIMARY KEY AUTOINCREMENT," + 2595224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + " INTEGER NOT NULL," + 2605224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_HEADER + " TEXT NOT NULL," + 2615224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_VALUE + " TEXT NOT NULL" + 2625224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard ");"); 26357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 26557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 26657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 26757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Initializes the content provider when it is created. 26857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 26957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 27057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public boolean onCreate() { 2716d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard if (mSystemFacade == null) { 272af28400b74de05862b470412a5c92f68e99f59f8Steve Howard mSystemFacade = new RealSystemFacade(getContext()); 2736d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard } 2746d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard 27557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project mOpenHelper = new DatabaseHelper(getContext()); 27691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // Initialize the system uid 27791e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu mSystemUid = Process.SYSTEM_UID; 27891e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // Initialize the default container uid. Package name hardcoded 27991e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // for now. 28091e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu ApplicationInfo appInfo = null; 28191e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu try { 28291e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu appInfo = getContext().getPackageManager(). 28391e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu getApplicationInfo("com.android.defcontainer", 0); 28491e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } catch (NameNotFoundException e) { 28591e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu // TODO Auto-generated catch block 28691e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu e.printStackTrace(); 28791e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } 28891e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu if (appInfo != null) { 28991e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu mDefContainerUid = appInfo.uid; 29091e4522fa90d969a596058756c24e173df1a6196Suchi Amalapurapu } 29157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return true; 29257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 29357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 29457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 29557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Returns the content-provider-style MIME types of the various 29657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * types accessible through this content provider. 29757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 29857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 29957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public String getType(final Uri uri) { 30057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 30157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 30257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 30357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_LIST_TYPE; 30457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 30557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 30657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return DOWNLOAD_TYPE; 30757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 30857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 30957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 31057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, "calling getType on an unknown URI: " + uri); 31157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 31257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 31357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 31457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 31557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 31657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 31757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 31857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Inserts a row in the database 31957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 32057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 32157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public Uri insert(final Uri uri, final ContentValues values) { 32257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 32357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 32457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (sURIMatcher.match(uri) != DOWNLOADS) { 32557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 32657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.d(Constants.TAG, "calling insert on an unknown/invalid URI: " + uri); 32757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 32857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown/Invalid URI " + uri); 32957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 33057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 3311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues = new ContentValues(); 3321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 3337dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_URI, values, filteredValues); 3347dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 3357dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyBoolean(Downloads.Impl.COLUMN_NO_INTEGRITY, values, filteredValues); 3367dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_FILE_NAME_HINT, values, filteredValues); 3377dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_MIME_TYPE, values, filteredValues); 3387dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION); 339ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (dest != null) { 3407dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 3411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project != PackageManager.PERMISSION_GRANTED 3427dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru && dest != Downloads.Impl.DESTINATION_EXTERNAL 3436d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard && dest != Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE 3446d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard && dest != Downloads.Impl.DESTINATION_FILE_URI) { 3451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("unauthorized destination code"); 3461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 3476d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard if (dest == Downloads.Impl.DESTINATION_FILE_URI) { 3486d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard getContext().enforcePermission( 3496d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard android.Manifest.permission.WRITE_EXTERNAL_STORAGE, 3506d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard Binder.getCallingPid(), Binder.getCallingUid(), 3516d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard "need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI"); 3526d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard } 3537dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_DESTINATION, dest); 354ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } 3557dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer vis = values.getAsInteger(Downloads.Impl.COLUMN_VISIBILITY); 356ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru if (vis == null) { 3577dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (dest == Downloads.Impl.DESTINATION_EXTERNAL) { 3587dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 3597dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); 360ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 3617dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, 3627dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Downloads.Impl.VISIBILITY_HIDDEN); 3631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 364ce8813afb256269e9e223f72ebced92560201bbbJean-Baptiste Queru } else { 3657dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, vis); 36657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3677dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 3687dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING); 3696d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, 3706d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard mSystemFacade.currentTimeMillis()); 3710a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 3720a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API, values, filteredValues); 3730a77c62a82503b38c484e0079648f0231dd85d53Steve Howard boolean isPublicApi = 3740a77c62a82503b38c484e0079648f0231dd85d53Steve Howard values.getAsBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API) == Boolean.TRUE; 3750a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 3767dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE); 3777dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS); 3780a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (pckg != null && (clazz != null || isPublicApi)) { 3791fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int uid = Binder.getCallingUid(); 3801fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project try { 3810a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (uid == 0 || mSystemFacade.userOwnsPackage(uid, pckg)) { 3827dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, pckg); 3830a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (clazz != null) { 3840a77c62a82503b38c484e0079648f0231dd85d53Steve Howard filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS, clazz); 3850a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 3861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 3871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } catch (PackageManager.NameNotFoundException ex) { 3881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project /* ignored for now */ 38957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 39057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3917dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues); 3927dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_COOKIE_DATA, values, filteredValues); 3937dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_USER_AGENT, values, filteredValues); 3947dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_REFERER, values, filteredValues); 3957dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED) 3961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project == PackageManager.PERMISSION_GRANTED) { 3977dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_OTHER_UID, values, filteredValues); 39857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 3991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues.put(Constants.UID, Binder.getCallingUid()); 4001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingUid() == 0) { 4011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project copyInteger(Constants.UID, values, filteredValues); 40257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 4037dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 4047dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 405b5629da794cb3c1ca1970d206343743b165b9644Steve Howard filteredValues.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1); 40657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4070a77c62a82503b38c484e0079648f0231dd85d53Steve Howard if (isPublicApi) { 4080a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyInteger(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, values, filteredValues); 4090a77c62a82503b38c484e0079648f0231dd85d53Steve Howard copyBoolean(Downloads.Impl.COLUMN_ALLOW_ROAMING, values, filteredValues); 4100a77c62a82503b38c484e0079648f0231dd85d53Steve Howard } 4110a77c62a82503b38c484e0079648f0231dd85d53Steve Howard 4121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGVV) { 4131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "initiating download with UID " 4141fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project + filteredValues.getAsInteger(Constants.UID)); 4157dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru if (filteredValues.containsKey(Downloads.Impl.COLUMN_OTHER_UID)) { 4161fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "other UID " + 4177dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.getAsInteger(Downloads.Impl.COLUMN_OTHER_UID)); 4181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 41957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 42057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Context context = getContext(); 42257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 42357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4241fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project long rowID = db.insert(DB_TABLE, null, filteredValues); 4255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard insertRequestHeaders(db, rowID, values); 42657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Uri ret = null; 42857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 42957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (rowID != -1) { 43057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 4317dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru ret = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + rowID); 43257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project context.getContentResolver().notifyChange(uri, null); 43357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 43457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 4351fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "couldn't insert into downloads database"); 43657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 43857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 43957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 44057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 44157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 44257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 44357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Starts a database query 44457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 44557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 4461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public Cursor query(final Uri uri, String[] projection, 44757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String selection, final String[] selectionArgs, 44857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String sort) { 4491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 4501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(selection, sAppReadableColumnsSet); 4511fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 45257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 45357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 45557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 45657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 45757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project boolean emptyWhere = true; 45857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 45957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: { 46057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 46157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 46257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 46357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 46457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project qb.setTables(DB_TABLE); 4657dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru qb.appendWhere(Downloads.Impl._ID + "="); 4665224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard qb.appendWhere(getDownloadIdFromUri(uri)); 46757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project emptyWhere = false; 46857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 46957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 4705224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard case REQUEST_HEADERS_URI: 4715224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (projection != null || selection != null || sort != null) { 4725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new UnsupportedOperationException("Request header queries do not support " 4735224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + "projections, selections or sorting"); 4745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 4755224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return queryRequestHeaders(db, uri); 47657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 47757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 4781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "querying unknown URI: " + uri); 47957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 48057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new IllegalArgumentException("Unknown URI: " + uri); 48157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 48257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 48357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 4845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (shouldRestrictVisibility()) { 4851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (projection == null) { 4861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project projection = sAppReadableColumnsArray; 4871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 4881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 4891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!sAppReadableColumnsSet.contains(projection[i])) { 4901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new IllegalArgumentException( 4911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project "column " + projection[i] + " is not allowed in queries"); 4921fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 4931fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 4941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 495a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (!emptyWhere) { 496a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins qb.appendWhere(" AND "); 497a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins emptyWhere = false; 498a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 4990d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard qb.appendWhere(getRestrictedUidClause()); 50057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 50157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 50257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 50357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project java.lang.StringBuilder sb = new java.lang.StringBuilder(); 50457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("starting query, database is "); 50557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (db != null) { 50657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("not "); 50757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 50857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("null; "); 50957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (projection == null) { 51057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is null; "); 51157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (projection.length == 0) { 51257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection is empty; "); 51357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 51457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < projection.length; ++i) { 51557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("projection["); 51657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 51757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 51857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(projection[i]); 51957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 52057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 52157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 52257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selection is "); 52357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selection); 52457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 52557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (selectionArgs == null) { 52657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is null; "); 52757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else if (selectionArgs.length == 0) { 52857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs is empty; "); 52957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 53057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project for (int i = 0; i < selectionArgs.length; ++i) { 53157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("selectionArgs["); 53257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(i); 53357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("] is "); 53457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(selectionArgs[i]); 53557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("; "); 53657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 53757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 53857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("sort is "); 53957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append(sort); 54057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project sb.append("."); 5411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, sb.toString()); 54257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 54357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 54457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Cursor ret = qb.query(db, projection, selection, selectionArgs, 54557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project null, null, sort); 54657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 54757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret != null) { 5481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ret = new ReadOnlyCursorWrapper(ret); 5491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 5501fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 5511fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (ret != null) { 55257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ret.setNotificationUri(getContext().getContentResolver(), uri); 55357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 55457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project Log.v(Constants.TAG, 55557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project "created cursor " + ret + " on behalf of " + Binder.getCallingPid()); 55657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 55757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 55857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGV) { 5591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "query failed in downloads database"); 56057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 56157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 56257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 56357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 56457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 56557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 5665224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private String getDownloadIdFromUri(final Uri uri) { 5675224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return uri.getPathSegments().get(1); 5685224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5695224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 5705224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 5715224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Insert request headers for a download into the DB. 5725224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 5735224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void insertRequestHeaders(SQLiteDatabase db, long downloadId, ContentValues values) { 5745224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard ContentValues rowValues = new ContentValues(); 5755224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID, downloadId); 5765224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (Map.Entry<String, Object> entry : values.valueSet()) { 5775224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String key = entry.getKey(); 5785224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (key.startsWith(Downloads.Impl.RequestHeaders.INSERT_KEY_PREFIX)) { 5795224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String headerLine = entry.getValue().toString(); 5805224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard if (!headerLine.contains(":")) { 5815224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard throw new IllegalArgumentException("Invalid HTTP header line: " + headerLine); 5825224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5835224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] parts = headerLine.split(":", 2); 5845224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_HEADER, parts[0].trim()); 5855224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard rowValues.put(Downloads.Impl.RequestHeaders.COLUMN_VALUE, parts[1].trim()); 5865224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.insert(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, null, rowValues); 5875224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5885224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5895224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 5905224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 5915224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 5925224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Handle a query for the custom request headers registered for a download. 5935224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 5945224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private Cursor queryRequestHeaders(SQLiteDatabase db, Uri uri) { 5955224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String where = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" 5965224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard + getDownloadIdFromUri(uri); 5975224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] projection = new String[] {Downloads.Impl.RequestHeaders.COLUMN_HEADER, 5985224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Downloads.Impl.RequestHeaders.COLUMN_VALUE}; 5995224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Cursor cursor = db.query(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, projection, where, 6005224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard null, null, null, null); 6015224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return new ReadOnlyCursorWrapper(cursor); 6025224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6035224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 6045224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 6055224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard * Delete request headers for downloads matching the given query. 6065224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 6075224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private void deleteRequestHeaders(SQLiteDatabase db, String where, String[] whereArgs) { 6085224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String[] projection = new String[] {Downloads.Impl._ID}; 6095224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Cursor cursor = db.query(DB_TABLE, projection , where, whereArgs, null, null, null, null); 6105224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard try { 6115224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { 6125224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard long id = cursor.getLong(0); 6135224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String idWhere = Downloads.Impl.RequestHeaders.COLUMN_DOWNLOAD_ID + "=" + id; 6145224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard db.delete(Downloads.Impl.RequestHeaders.HEADERS_DB_TABLE, idWhere, null); 6155224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6165224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } finally { 6175224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard cursor.close(); 6185224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6195224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6205224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 6215224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard /** 6220d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard * @return true if we should restrict this caller to viewing only its own downloads 6235224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard */ 6245224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard private boolean shouldRestrictVisibility() { 6255224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard int callingUid = Binder.getCallingUid(); 6265224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard return Binder.getCallingPid() != Process.myPid() && 6275224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard callingUid != mSystemUid && 6285224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard callingUid != mDefContainerUid && 6295224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard Process.supportsProcesses(); 6305224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard } 6315224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard 63257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 6330d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard * @return a SQL WHERE clause to restrict the query to downloads accessible to the caller's UID 6340d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard */ 6350d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard private String getRestrictedUidClause() { 6360d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard return "( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " 6370d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"; 6380d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard } 6390d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard 6400d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard /** 64157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Updates a row in the database 64257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 64357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 64457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int update(final Uri uri, final ContentValues values, 64557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String where, final String[] whereArgs) { 6461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 6481fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 64957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 65057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 65157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 65257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = 0; 6531fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project boolean startService = false; 6541fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 6551fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ContentValues filteredValues; 6561fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Binder.getCallingPid() != Process.myPid()) { 6571fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = new ContentValues(); 6587dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues); 6597dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_VISIBILITY, values, filteredValues); 6607dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Integer i = values.getAsInteger(Downloads.Impl.COLUMN_CONTROL); 6611fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 6627dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru filteredValues.put(Downloads.Impl.COLUMN_CONTROL, i); 6631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project startService = true; 6641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 6657dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues); 6667dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_TITLE, values, filteredValues); 6677dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); 6681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 6691fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project filteredValues = values; 670a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins String filename = values.getAsString(Downloads.Impl._DATA); 671a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (filename != null) { 672a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins Cursor c = query(uri, new String[] 673a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins { Downloads.Impl.COLUMN_TITLE }, null, null, null); 674a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins if (!c.moveToFirst() || c.getString(0) == null) { 675a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins values.put(Downloads.Impl.COLUMN_TITLE, 676a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins new File(filename).getName()); 677a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 678a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins c.close(); 679a2028ed4141075da8199ba04a499be77734a85aeLeon Scroggins } 68057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 68157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 68257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 68357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 68457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 68557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 68657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 68757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 6881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 68957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 6901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 69157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 69257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 69357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 69457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 69557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 6965224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String segment = getDownloadIdFromUri(uri); 69757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project rowId = Long.parseLong(segment); 6987dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 69957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7000d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard if (shouldRestrictVisibility()) { 7010d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard myWhere += " AND " + getRestrictedUidClause(); 70257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (filteredValues.size() > 0) { 7041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = db.update(DB_TABLE, filteredValues, myWhere, whereArgs); 7051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } else { 7061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project count = 0; 7071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 70857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 70957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 71057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 71157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 7121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "updating unknown/invalid URI: " + uri); 71357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 71457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot update URI: " + uri); 71557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 71657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 71757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 7181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (startService) { 7191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Context context = getContext(); 7201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project context.startService(new Intent(context, DownloadService.class)); 7211fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 72257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 72357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 72457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 72557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 72657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Deletes a row in the database 72757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 72857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 72957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public int delete(final Uri uri, final String where, 73057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project final String[] whereArgs) { 7311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 7321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Helpers.validateSelection(where, sAppReadableColumnsSet); 7331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 73457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 73557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int count; 73657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project int match = sURIMatcher.match(uri); 73757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project switch (match) { 73857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS: 73957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project case DOWNLOADS_ID: { 74057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String myWhere; 74157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (where != null) { 74257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS) { 7431fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " )"; 74457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 7451fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project myWhere = "( " + where + " ) AND "; 74657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 74757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 74857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project myWhere = ""; 74957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 75057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (match == DOWNLOADS_ID) { 7515224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard String segment = getDownloadIdFromUri(uri); 75257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project long rowId = Long.parseLong(segment); 7537dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru myWhere += " ( " + Downloads.Impl._ID + " = " + rowId + " ) "; 75457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7550d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard if (shouldRestrictVisibility()) { 7560d8d89105c00edbad95a268aaae65f2ff94ed5a1Steve Howard myWhere += " AND " + getRestrictedUidClause(); 75757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 7585224c6fbf20b4803a580ef449ab87ebfbbfedb78Steve Howard deleteRequestHeaders(db, where, whereArgs); 75957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project count = db.delete(DB_TABLE, myWhere, whereArgs); 76057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project break; 76157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project default: { 76357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Config.LOGD) { 7641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.d(Constants.TAG, "deleting unknown/invalid URI: " + uri); 76557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throw new UnsupportedOperationException("Cannot delete URI: " + uri); 76757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 76957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 77057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return count; 77157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 77257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 77357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project /** 77457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project * Remotely opens a file 77557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project */ 77657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project @Override 77757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project public ParcelFileDescriptor openFile(Uri uri, String mode) 77857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project throws FileNotFoundException { 77957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (Constants.LOGVV) { 7801fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "openFile uri: " + uri + ", mode: " + mode 78157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project + ", uid: " + Binder.getCallingUid()); 7827dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru Cursor cursor = query(Downloads.Impl.CONTENT_URI, 7837dd92fa94df0a13b4592ee636b7aa2b605f6b473Jean-Baptiste Queru new String[] { "_id" }, null, null, "_id"); 78457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 7851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 78657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 78757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 7881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 78957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 79057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project do { 7911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "row " + cursor.getInt(0) + " available"); 79257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } while(cursor.moveToNext()); 79357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 79457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 79557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 79657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor = query(uri, new String[] { "_data" }, null, null, null); 79757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (cursor == null) { 7981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "null cursor in openFile"); 79957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 80057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (!cursor.moveToFirst()) { 8011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "empty cursor in openFile"); 80257f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 80357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project String filename = cursor.getString(0); 8041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "filename in openFile: " + filename); 80557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (new java.io.File(filename).isFile()) { 8061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "file exists in openFile"); 80757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 80857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 80957f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project cursor.close(); 81057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 81157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 8121fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8131fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // This logic is mostly copied form openFileHelper. If openFileHelper eventually 8141fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // gets split into small bits (to extract the filename and the modebits), 8151fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // this code could use the separate bits and be deeply simplified. 8161fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Cursor c = query(uri, new String[]{"_data"}, null, null, null); 8171fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project int count = (c != null) ? c.getCount() : 0; 8181fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count != 1) { 8191fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project // If there is not exactly one result, throw an appropriate exception. 8201fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (c != null) { 8211fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 8221fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8231fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (count == 0) { 8241fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No entry for " + uri); 8251fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8261fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Multiple items at " + uri); 8271fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8281fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8291fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.moveToFirst(); 8301fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String path = c.getString(0); 8311fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project c.close(); 8321fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (path == null) { 8331fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("No filename found."); 8341fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8351fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!Helpers.isFilenameValid(path)) { 8361fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Invalid filename."); 8371fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8381fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8391fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (!"r".equals(mode)) { 8401fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("Bad mode for " + uri + ": " + mode); 8411fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8421fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor ret = ParcelFileDescriptor.open(new File(path), 8431fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project ParcelFileDescriptor.MODE_READ_ONLY); 8441fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 84557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project if (ret == null) { 8461fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (Constants.LOGV) { 8471fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Log.v(Constants.TAG, "couldn't open file"); 84857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 8491fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new FileNotFoundException("couldn't open file"); 85057f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } else { 85157f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project ContentValues values = new ContentValues(); 8526d9b98282c817b86a00f9c19a705da4cb19bc3a6Steve Howard values.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, mSystemFacade.currentTimeMillis()); 85357f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project update(uri, values, null, null); 85457f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 85557f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project return ret; 85657f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project } 85757f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project 8581fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyInteger(String key, ContentValues from, ContentValues to) { 8591fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Integer i = from.getAsInteger(key); 8601fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (i != null) { 8611fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, i); 8621fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8631fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8641fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8651fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyBoolean(String key, ContentValues from, ContentValues to) { 8661fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project Boolean b = from.getAsBoolean(key); 8671fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (b != null) { 8681fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, b); 8691fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8701fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8711fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8721fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private static final void copyString(String key, ContentValues from, ContentValues to) { 8731fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project String s = from.getAsString(key); 8741fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project if (s != null) { 8751fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project to.put(key, s); 8761fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8771fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8781fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8791fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private class ReadOnlyCursorWrapper extends CursorWrapper implements CrossProcessCursor { 8801fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public ReadOnlyCursorWrapper(Cursor cursor) { 8811fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project super(cursor); 8821fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor = (CrossProcessCursor) cursor; 8831fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8841fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8851fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean deleteRow() { 8861fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 8871fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8881fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8891fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean commitUpdates() { 8901fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project throw new SecurityException("Download manager cursors are read-only"); 8911fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8921fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8931fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public void fillWindow(int pos, CursorWindow window) { 8941fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project mCursor.fillWindow(pos, window); 8951fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 8961fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 8971fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public CursorWindow getWindow() { 8981fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.getWindow(); 8991fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9001fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9011fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project public boolean onMove(int oldPosition, int newPosition) { 9021fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project return mCursor.onMove(oldPosition, newPosition); 9031fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9041fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 9051fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project private CrossProcessCursor mCursor; 9061fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project } 9071fbad9cfa532f13f6cf03f542febf2e4689edec5The Android Open Source Project 90857f55b3cb4f7e4136cde8d1ea12c1e70ec90336The Android Open Source Project} 909